Avoiding the `goto` voodoo?
I have a switch
structure that has several cases to handle. The switch
operates over an enum
which presents duplicate code issues:
public enum ExampleEnum {
One,
OneAndTwo,
OneAndThree,
Two,
TwoAndThree,
Three
}
When I enter the switch
structure, the functionality for One
, Two
, and Three
are the same even when coupled together. For example:
int i = 0;
if (One || OneAndTwo || OneAndThree)
i++;
if (Two || OneAndTwo || TwoAndThree)
i += 2;
if (Three || OneAndThree || TwoAndThree)
i += 3;
Pretty great and simple stuff right? Well the switch
structure can get kind of ugly (so can the if
structure) in this scenario so I figured that this may be an acceptable use of the goto
statement:
switch (exampleValue) {
case OneAndTwo: i += 2 goto default;
case OneAndThree: i += 3 goto default;
case Two: i += 2 break;
case TwoAndThree: i += 2 goto case Three;
case Three: i += 3 break;
default: i++ break;
}
I see no issue with the code above since it is sequential in nature and isn't misleading as to what could occur; however, this is just my opinion and I know there is a big debate over the use of goto
within a professional environment. I currently have this refactored out into an if
statement which definitely does what it should, but I hate the duplication factor of it. Why duplicate code when I can just tell it to execute both chunks. Even in my example above there is code duplication and I'd love to remove that too, but that would require more thought.
Important Notes
I have edited the post to remove the need for comments related to:
- Execution path.
- Calling methods.
The
switch
structure example above is not actually implemented in my code.- I am looking for alternatives to handling cases of fall-through.
- The execution order for each case is irrelevant in this particular code.
In this particular case the switch
structure has cases which should fall-through to other cases which is not supported in C#
like it is with C
, C++
, and Java
. Would this be an acceptable use in a professional environment or should I leave it as my if
structure?
Is there a more concise way of accomplishing this without effecting readability and maintainability?
c# switch-statement goto
|
show 2 more comments
I have a switch
structure that has several cases to handle. The switch
operates over an enum
which presents duplicate code issues:
public enum ExampleEnum {
One,
OneAndTwo,
OneAndThree,
Two,
TwoAndThree,
Three
}
When I enter the switch
structure, the functionality for One
, Two
, and Three
are the same even when coupled together. For example:
int i = 0;
if (One || OneAndTwo || OneAndThree)
i++;
if (Two || OneAndTwo || TwoAndThree)
i += 2;
if (Three || OneAndThree || TwoAndThree)
i += 3;
Pretty great and simple stuff right? Well the switch
structure can get kind of ugly (so can the if
structure) in this scenario so I figured that this may be an acceptable use of the goto
statement:
switch (exampleValue) {
case OneAndTwo: i += 2 goto default;
case OneAndThree: i += 3 goto default;
case Two: i += 2 break;
case TwoAndThree: i += 2 goto case Three;
case Three: i += 3 break;
default: i++ break;
}
I see no issue with the code above since it is sequential in nature and isn't misleading as to what could occur; however, this is just my opinion and I know there is a big debate over the use of goto
within a professional environment. I currently have this refactored out into an if
statement which definitely does what it should, but I hate the duplication factor of it. Why duplicate code when I can just tell it to execute both chunks. Even in my example above there is code duplication and I'd love to remove that too, but that would require more thought.
Important Notes
I have edited the post to remove the need for comments related to:
- Execution path.
- Calling methods.
The
switch
structure example above is not actually implemented in my code.- I am looking for alternatives to handling cases of fall-through.
- The execution order for each case is irrelevant in this particular code.
In this particular case the switch
structure has cases which should fall-through to other cases which is not supported in C#
like it is with C
, C++
, and Java
. Would this be an acceptable use in a professional environment or should I leave it as my if
structure?
Is there a more concise way of accomplishing this without effecting readability and maintainability?
c# switch-statement goto
5
there is no big debate. no one uses goto. make your enum a flag
– Ewan
6 hours ago
2
@Ewan Hence there is a big debate; there are scenarios wheregoto
should be used, but in modern code it's usually for obfuscation purposes.
– PerpetualJ
5 hours ago
1
it sounds like you want to have a big debate. But you'll need a better example of a good case to use goto. flag enum neatly solves this one, even if your if statement example wasnt acceptable and it looks fine to me
– Ewan
5 hours ago
@Ewan I'm here to avoid using it and am looking for alternatives (a fantastic one has already been offered), but to since you stated I'd need a better example; the current post is a good example sinceC#
doesn't allow fall-through in theswitch
structure likeC
,C++
, andJava
. This is per the documentation over on MSDN; however, I believe we are getting off topic at this point.
– PerpetualJ
5 hours ago
1
@Ewan No one uses the goto. When is the last time you looked at the Linux kernel source code?
– John Douma
2 hours ago
|
show 2 more comments
I have a switch
structure that has several cases to handle. The switch
operates over an enum
which presents duplicate code issues:
public enum ExampleEnum {
One,
OneAndTwo,
OneAndThree,
Two,
TwoAndThree,
Three
}
When I enter the switch
structure, the functionality for One
, Two
, and Three
are the same even when coupled together. For example:
int i = 0;
if (One || OneAndTwo || OneAndThree)
i++;
if (Two || OneAndTwo || TwoAndThree)
i += 2;
if (Three || OneAndThree || TwoAndThree)
i += 3;
Pretty great and simple stuff right? Well the switch
structure can get kind of ugly (so can the if
structure) in this scenario so I figured that this may be an acceptable use of the goto
statement:
switch (exampleValue) {
case OneAndTwo: i += 2 goto default;
case OneAndThree: i += 3 goto default;
case Two: i += 2 break;
case TwoAndThree: i += 2 goto case Three;
case Three: i += 3 break;
default: i++ break;
}
I see no issue with the code above since it is sequential in nature and isn't misleading as to what could occur; however, this is just my opinion and I know there is a big debate over the use of goto
within a professional environment. I currently have this refactored out into an if
statement which definitely does what it should, but I hate the duplication factor of it. Why duplicate code when I can just tell it to execute both chunks. Even in my example above there is code duplication and I'd love to remove that too, but that would require more thought.
Important Notes
I have edited the post to remove the need for comments related to:
- Execution path.
- Calling methods.
The
switch
structure example above is not actually implemented in my code.- I am looking for alternatives to handling cases of fall-through.
- The execution order for each case is irrelevant in this particular code.
In this particular case the switch
structure has cases which should fall-through to other cases which is not supported in C#
like it is with C
, C++
, and Java
. Would this be an acceptable use in a professional environment or should I leave it as my if
structure?
Is there a more concise way of accomplishing this without effecting readability and maintainability?
c# switch-statement goto
I have a switch
structure that has several cases to handle. The switch
operates over an enum
which presents duplicate code issues:
public enum ExampleEnum {
One,
OneAndTwo,
OneAndThree,
Two,
TwoAndThree,
Three
}
When I enter the switch
structure, the functionality for One
, Two
, and Three
are the same even when coupled together. For example:
int i = 0;
if (One || OneAndTwo || OneAndThree)
i++;
if (Two || OneAndTwo || TwoAndThree)
i += 2;
if (Three || OneAndThree || TwoAndThree)
i += 3;
Pretty great and simple stuff right? Well the switch
structure can get kind of ugly (so can the if
structure) in this scenario so I figured that this may be an acceptable use of the goto
statement:
switch (exampleValue) {
case OneAndTwo: i += 2 goto default;
case OneAndThree: i += 3 goto default;
case Two: i += 2 break;
case TwoAndThree: i += 2 goto case Three;
case Three: i += 3 break;
default: i++ break;
}
I see no issue with the code above since it is sequential in nature and isn't misleading as to what could occur; however, this is just my opinion and I know there is a big debate over the use of goto
within a professional environment. I currently have this refactored out into an if
statement which definitely does what it should, but I hate the duplication factor of it. Why duplicate code when I can just tell it to execute both chunks. Even in my example above there is code duplication and I'd love to remove that too, but that would require more thought.
Important Notes
I have edited the post to remove the need for comments related to:
- Execution path.
- Calling methods.
The
switch
structure example above is not actually implemented in my code.- I am looking for alternatives to handling cases of fall-through.
- The execution order for each case is irrelevant in this particular code.
In this particular case the switch
structure has cases which should fall-through to other cases which is not supported in C#
like it is with C
, C++
, and Java
. Would this be an acceptable use in a professional environment or should I leave it as my if
structure?
Is there a more concise way of accomplishing this without effecting readability and maintainability?
c# switch-statement goto
c# switch-statement goto
edited 2 hours ago
PerpetualJ
asked 6 hours ago
PerpetualJPerpetualJ
1517
1517
5
there is no big debate. no one uses goto. make your enum a flag
– Ewan
6 hours ago
2
@Ewan Hence there is a big debate; there are scenarios wheregoto
should be used, but in modern code it's usually for obfuscation purposes.
– PerpetualJ
5 hours ago
1
it sounds like you want to have a big debate. But you'll need a better example of a good case to use goto. flag enum neatly solves this one, even if your if statement example wasnt acceptable and it looks fine to me
– Ewan
5 hours ago
@Ewan I'm here to avoid using it and am looking for alternatives (a fantastic one has already been offered), but to since you stated I'd need a better example; the current post is a good example sinceC#
doesn't allow fall-through in theswitch
structure likeC
,C++
, andJava
. This is per the documentation over on MSDN; however, I believe we are getting off topic at this point.
– PerpetualJ
5 hours ago
1
@Ewan No one uses the goto. When is the last time you looked at the Linux kernel source code?
– John Douma
2 hours ago
|
show 2 more comments
5
there is no big debate. no one uses goto. make your enum a flag
– Ewan
6 hours ago
2
@Ewan Hence there is a big debate; there are scenarios wheregoto
should be used, but in modern code it's usually for obfuscation purposes.
– PerpetualJ
5 hours ago
1
it sounds like you want to have a big debate. But you'll need a better example of a good case to use goto. flag enum neatly solves this one, even if your if statement example wasnt acceptable and it looks fine to me
– Ewan
5 hours ago
@Ewan I'm here to avoid using it and am looking for alternatives (a fantastic one has already been offered), but to since you stated I'd need a better example; the current post is a good example sinceC#
doesn't allow fall-through in theswitch
structure likeC
,C++
, andJava
. This is per the documentation over on MSDN; however, I believe we are getting off topic at this point.
– PerpetualJ
5 hours ago
1
@Ewan No one uses the goto. When is the last time you looked at the Linux kernel source code?
– John Douma
2 hours ago
5
5
there is no big debate. no one uses goto. make your enum a flag
– Ewan
6 hours ago
there is no big debate. no one uses goto. make your enum a flag
– Ewan
6 hours ago
2
2
@Ewan Hence there is a big debate; there are scenarios where
goto
should be used, but in modern code it's usually for obfuscation purposes.– PerpetualJ
5 hours ago
@Ewan Hence there is a big debate; there are scenarios where
goto
should be used, but in modern code it's usually for obfuscation purposes.– PerpetualJ
5 hours ago
1
1
it sounds like you want to have a big debate. But you'll need a better example of a good case to use goto. flag enum neatly solves this one, even if your if statement example wasnt acceptable and it looks fine to me
– Ewan
5 hours ago
it sounds like you want to have a big debate. But you'll need a better example of a good case to use goto. flag enum neatly solves this one, even if your if statement example wasnt acceptable and it looks fine to me
– Ewan
5 hours ago
@Ewan I'm here to avoid using it and am looking for alternatives (a fantastic one has already been offered), but to since you stated I'd need a better example; the current post is a good example since
C#
doesn't allow fall-through in the switch
structure like C
, C++
, and Java
. This is per the documentation over on MSDN; however, I believe we are getting off topic at this point.– PerpetualJ
5 hours ago
@Ewan I'm here to avoid using it and am looking for alternatives (a fantastic one has already been offered), but to since you stated I'd need a better example; the current post is a good example since
C#
doesn't allow fall-through in the switch
structure like C
, C++
, and Java
. This is per the documentation over on MSDN; however, I believe we are getting off topic at this point.– PerpetualJ
5 hours ago
1
1
@Ewan No one uses the goto. When is the last time you looked at the Linux kernel source code?
– John Douma
2 hours ago
@Ewan No one uses the goto. When is the last time you looked at the Linux kernel source code?
– John Douma
2 hours ago
|
show 2 more comments
3 Answers
3
active
oldest
votes
I find the code hard to read with the goto
statements. I would recommend structuring your enum
differently. For example, if your enum
was a bitfield where each bit represented one of the choices, it could look like this:
[Flags]
public enum ExampleEnum {
One = 0b0001,
Two = 0b0010,
Three = 0b0100
};
The Flags attribute tells the compiler that you're setting up values which don't overlap. The code that calls this code could set the appropriate bit. You could then do something like this to make it clear what's happening:
if (myEnum.HasFlag(ExampleEnum.One))
{
CallOne();
}
if (myEnum.HasFlag(ExampleEnum.Two))
{
CallTwo();
}
if (myEnum.HasFlag(ExampleEnum.Three))
{
CallThree();
}
This requires the code that sets up myEnum
to set the bitfields properly and marked with the Flags attribute. But you can do that by changing the values of the enums in your example to:
[Flags]
public enum ExampleEnum {
One = 0b0001,
Two = 0b0010,
Three = 0b0100,
OneAndTwo = One | Two,
OneAndThree = One | Three,
TwoAndThree = Two | Three
};
When you write a number in the form 0bxxxx
, you're specifying it in binary. So you can see that we set bit 1, 2, or 3 (well, technically 0, 1, or 2, but you get the idea). You can also name combinations by using a bitwise OR if the combinations might be frequently set together.
Does C# have binary constants? Usually I use hex for flags but this is a case where binary would be superior.
– user949300
5 hours ago
2
It appears so! But it must be C# 7.0 or later, I guess.
– user1118321
5 hours ago
4
Anyway, one could also do it like this:public enum ExampleEnum { One = 1 << 0, Two = 1 << 1, Three = 1 << 2, OneAndTwo = One | Two, OneAndThree = One | Three, TwoAndThree = Two | Three };
. No need to insist on C#7+.
– Deduplicator
5 hours ago
1
You may use Enum.HasFlag
– IMil
4 hours ago
2
The[Flags]
attribute doesn't signal anything to the compiler. This is why you still have to explicitly declare the enum values as powers of 2.
– Joe Sewell
2 hours ago
|
show 3 more comments
The best answer is use polymorphism.
Another answer, which, IMO, makes the if stuff clearer and arguably shorter:
if (One || OneAndTwo)
CallOne();
if (OneAndTwo || Two)
CallTwo();
if (OneAndThree || TwoAndThree || Three)
CallThree();
goto
is probably my 58th choice here...
1
+1 for suggesting polymorphism, though ideally that might simplify the client code down to just "Call();", using tell don't ask -- to push the decision logic away from the consuming client and into the class mechanism and hierarchy.
– Erik Eidt
5 hours ago
1
Proclaiming anything the best sight unseen is certainly very brave. But without additional info, I suggest a bit of scepticism and keeping an open mind. Perhaps it suffers from combinatorial explosion?
– Deduplicator
4 hours ago
Wow, I think this is the first time I've ever been downvoted for suggesting polymorphism. :-)
– user949300
4 hours ago
add a comment |
IMO the root of the problem is that this piece of code shouldn't even exist.
You apparently have three independent conditions, and three independent actions to take if those conditions are true. So why is all that being funnelled into one piece of code that needs three Boolean flags to tell it what to do (whether or not you obfuscate them into an enum) and then does some combination of three independent things? The single responsibility principle seems to be having an off-day here.
Put the calls to the three functions where the belong (i.e. where you discover the need to do the actions) and consign the code in these examples to the recycle bin.
If there were ten flags and actions not three, would you extend this sort of code to handle 1024 different combinations? I hope not! If 1024 is too many, 8 is also too many, for the same reason.
So grateful for this answer! In my opinion the code is perfectly valid and genericized for this particular post. The question is in relation to thegoto
statement and not the concept of single responsibility. I have refactored the code to handle everything with four simpleif
statements. More to the point on your answer, there is nothing wrong with multiple if statements in the same method so long as they achieve a related goal to the method and simply alter the execution path. In my actual code each piece isn't actually a method call, but a single line execution.
– PerpetualJ
2 hours ago
1
As a point of fact, there are many well-designed APIs which have all kinds of flags, options, and assorted other parameters. Some may be passed on, some have direct effects, and yet others potentially be ignored, without breaking SRP. Anyway, the function could even be decoding some external input, who knows? Also, reductio ad absurdum often leads to absurd results, especially if the starting-point isn't even all that solid.
– Deduplicator
2 hours ago
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "131"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f385901%2favoiding-the-goto-voodoo%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
I find the code hard to read with the goto
statements. I would recommend structuring your enum
differently. For example, if your enum
was a bitfield where each bit represented one of the choices, it could look like this:
[Flags]
public enum ExampleEnum {
One = 0b0001,
Two = 0b0010,
Three = 0b0100
};
The Flags attribute tells the compiler that you're setting up values which don't overlap. The code that calls this code could set the appropriate bit. You could then do something like this to make it clear what's happening:
if (myEnum.HasFlag(ExampleEnum.One))
{
CallOne();
}
if (myEnum.HasFlag(ExampleEnum.Two))
{
CallTwo();
}
if (myEnum.HasFlag(ExampleEnum.Three))
{
CallThree();
}
This requires the code that sets up myEnum
to set the bitfields properly and marked with the Flags attribute. But you can do that by changing the values of the enums in your example to:
[Flags]
public enum ExampleEnum {
One = 0b0001,
Two = 0b0010,
Three = 0b0100,
OneAndTwo = One | Two,
OneAndThree = One | Three,
TwoAndThree = Two | Three
};
When you write a number in the form 0bxxxx
, you're specifying it in binary. So you can see that we set bit 1, 2, or 3 (well, technically 0, 1, or 2, but you get the idea). You can also name combinations by using a bitwise OR if the combinations might be frequently set together.
Does C# have binary constants? Usually I use hex for flags but this is a case where binary would be superior.
– user949300
5 hours ago
2
It appears so! But it must be C# 7.0 or later, I guess.
– user1118321
5 hours ago
4
Anyway, one could also do it like this:public enum ExampleEnum { One = 1 << 0, Two = 1 << 1, Three = 1 << 2, OneAndTwo = One | Two, OneAndThree = One | Three, TwoAndThree = Two | Three };
. No need to insist on C#7+.
– Deduplicator
5 hours ago
1
You may use Enum.HasFlag
– IMil
4 hours ago
2
The[Flags]
attribute doesn't signal anything to the compiler. This is why you still have to explicitly declare the enum values as powers of 2.
– Joe Sewell
2 hours ago
|
show 3 more comments
I find the code hard to read with the goto
statements. I would recommend structuring your enum
differently. For example, if your enum
was a bitfield where each bit represented one of the choices, it could look like this:
[Flags]
public enum ExampleEnum {
One = 0b0001,
Two = 0b0010,
Three = 0b0100
};
The Flags attribute tells the compiler that you're setting up values which don't overlap. The code that calls this code could set the appropriate bit. You could then do something like this to make it clear what's happening:
if (myEnum.HasFlag(ExampleEnum.One))
{
CallOne();
}
if (myEnum.HasFlag(ExampleEnum.Two))
{
CallTwo();
}
if (myEnum.HasFlag(ExampleEnum.Three))
{
CallThree();
}
This requires the code that sets up myEnum
to set the bitfields properly and marked with the Flags attribute. But you can do that by changing the values of the enums in your example to:
[Flags]
public enum ExampleEnum {
One = 0b0001,
Two = 0b0010,
Three = 0b0100,
OneAndTwo = One | Two,
OneAndThree = One | Three,
TwoAndThree = Two | Three
};
When you write a number in the form 0bxxxx
, you're specifying it in binary. So you can see that we set bit 1, 2, or 3 (well, technically 0, 1, or 2, but you get the idea). You can also name combinations by using a bitwise OR if the combinations might be frequently set together.
Does C# have binary constants? Usually I use hex for flags but this is a case where binary would be superior.
– user949300
5 hours ago
2
It appears so! But it must be C# 7.0 or later, I guess.
– user1118321
5 hours ago
4
Anyway, one could also do it like this:public enum ExampleEnum { One = 1 << 0, Two = 1 << 1, Three = 1 << 2, OneAndTwo = One | Two, OneAndThree = One | Three, TwoAndThree = Two | Three };
. No need to insist on C#7+.
– Deduplicator
5 hours ago
1
You may use Enum.HasFlag
– IMil
4 hours ago
2
The[Flags]
attribute doesn't signal anything to the compiler. This is why you still have to explicitly declare the enum values as powers of 2.
– Joe Sewell
2 hours ago
|
show 3 more comments
I find the code hard to read with the goto
statements. I would recommend structuring your enum
differently. For example, if your enum
was a bitfield where each bit represented one of the choices, it could look like this:
[Flags]
public enum ExampleEnum {
One = 0b0001,
Two = 0b0010,
Three = 0b0100
};
The Flags attribute tells the compiler that you're setting up values which don't overlap. The code that calls this code could set the appropriate bit. You could then do something like this to make it clear what's happening:
if (myEnum.HasFlag(ExampleEnum.One))
{
CallOne();
}
if (myEnum.HasFlag(ExampleEnum.Two))
{
CallTwo();
}
if (myEnum.HasFlag(ExampleEnum.Three))
{
CallThree();
}
This requires the code that sets up myEnum
to set the bitfields properly and marked with the Flags attribute. But you can do that by changing the values of the enums in your example to:
[Flags]
public enum ExampleEnum {
One = 0b0001,
Two = 0b0010,
Three = 0b0100,
OneAndTwo = One | Two,
OneAndThree = One | Three,
TwoAndThree = Two | Three
};
When you write a number in the form 0bxxxx
, you're specifying it in binary. So you can see that we set bit 1, 2, or 3 (well, technically 0, 1, or 2, but you get the idea). You can also name combinations by using a bitwise OR if the combinations might be frequently set together.
I find the code hard to read with the goto
statements. I would recommend structuring your enum
differently. For example, if your enum
was a bitfield where each bit represented one of the choices, it could look like this:
[Flags]
public enum ExampleEnum {
One = 0b0001,
Two = 0b0010,
Three = 0b0100
};
The Flags attribute tells the compiler that you're setting up values which don't overlap. The code that calls this code could set the appropriate bit. You could then do something like this to make it clear what's happening:
if (myEnum.HasFlag(ExampleEnum.One))
{
CallOne();
}
if (myEnum.HasFlag(ExampleEnum.Two))
{
CallTwo();
}
if (myEnum.HasFlag(ExampleEnum.Three))
{
CallThree();
}
This requires the code that sets up myEnum
to set the bitfields properly and marked with the Flags attribute. But you can do that by changing the values of the enums in your example to:
[Flags]
public enum ExampleEnum {
One = 0b0001,
Two = 0b0010,
Three = 0b0100,
OneAndTwo = One | Two,
OneAndThree = One | Three,
TwoAndThree = Two | Three
};
When you write a number in the form 0bxxxx
, you're specifying it in binary. So you can see that we set bit 1, 2, or 3 (well, technically 0, 1, or 2, but you get the idea). You can also name combinations by using a bitwise OR if the combinations might be frequently set together.
edited 2 hours ago
Andy
1,073819
1,073819
answered 5 hours ago
user1118321user1118321
3,729719
3,729719
Does C# have binary constants? Usually I use hex for flags but this is a case where binary would be superior.
– user949300
5 hours ago
2
It appears so! But it must be C# 7.0 or later, I guess.
– user1118321
5 hours ago
4
Anyway, one could also do it like this:public enum ExampleEnum { One = 1 << 0, Two = 1 << 1, Three = 1 << 2, OneAndTwo = One | Two, OneAndThree = One | Three, TwoAndThree = Two | Three };
. No need to insist on C#7+.
– Deduplicator
5 hours ago
1
You may use Enum.HasFlag
– IMil
4 hours ago
2
The[Flags]
attribute doesn't signal anything to the compiler. This is why you still have to explicitly declare the enum values as powers of 2.
– Joe Sewell
2 hours ago
|
show 3 more comments
Does C# have binary constants? Usually I use hex for flags but this is a case where binary would be superior.
– user949300
5 hours ago
2
It appears so! But it must be C# 7.0 or later, I guess.
– user1118321
5 hours ago
4
Anyway, one could also do it like this:public enum ExampleEnum { One = 1 << 0, Two = 1 << 1, Three = 1 << 2, OneAndTwo = One | Two, OneAndThree = One | Three, TwoAndThree = Two | Three };
. No need to insist on C#7+.
– Deduplicator
5 hours ago
1
You may use Enum.HasFlag
– IMil
4 hours ago
2
The[Flags]
attribute doesn't signal anything to the compiler. This is why you still have to explicitly declare the enum values as powers of 2.
– Joe Sewell
2 hours ago
Does C# have binary constants? Usually I use hex for flags but this is a case where binary would be superior.
– user949300
5 hours ago
Does C# have binary constants? Usually I use hex for flags but this is a case where binary would be superior.
– user949300
5 hours ago
2
2
It appears so! But it must be C# 7.0 or later, I guess.
– user1118321
5 hours ago
It appears so! But it must be C# 7.0 or later, I guess.
– user1118321
5 hours ago
4
4
Anyway, one could also do it like this:
public enum ExampleEnum { One = 1 << 0, Two = 1 << 1, Three = 1 << 2, OneAndTwo = One | Two, OneAndThree = One | Three, TwoAndThree = Two | Three };
. No need to insist on C#7+.– Deduplicator
5 hours ago
Anyway, one could also do it like this:
public enum ExampleEnum { One = 1 << 0, Two = 1 << 1, Three = 1 << 2, OneAndTwo = One | Two, OneAndThree = One | Three, TwoAndThree = Two | Three };
. No need to insist on C#7+.– Deduplicator
5 hours ago
1
1
You may use Enum.HasFlag
– IMil
4 hours ago
You may use Enum.HasFlag
– IMil
4 hours ago
2
2
The
[Flags]
attribute doesn't signal anything to the compiler. This is why you still have to explicitly declare the enum values as powers of 2.– Joe Sewell
2 hours ago
The
[Flags]
attribute doesn't signal anything to the compiler. This is why you still have to explicitly declare the enum values as powers of 2.– Joe Sewell
2 hours ago
|
show 3 more comments
The best answer is use polymorphism.
Another answer, which, IMO, makes the if stuff clearer and arguably shorter:
if (One || OneAndTwo)
CallOne();
if (OneAndTwo || Two)
CallTwo();
if (OneAndThree || TwoAndThree || Three)
CallThree();
goto
is probably my 58th choice here...
1
+1 for suggesting polymorphism, though ideally that might simplify the client code down to just "Call();", using tell don't ask -- to push the decision logic away from the consuming client and into the class mechanism and hierarchy.
– Erik Eidt
5 hours ago
1
Proclaiming anything the best sight unseen is certainly very brave. But without additional info, I suggest a bit of scepticism and keeping an open mind. Perhaps it suffers from combinatorial explosion?
– Deduplicator
4 hours ago
Wow, I think this is the first time I've ever been downvoted for suggesting polymorphism. :-)
– user949300
4 hours ago
add a comment |
The best answer is use polymorphism.
Another answer, which, IMO, makes the if stuff clearer and arguably shorter:
if (One || OneAndTwo)
CallOne();
if (OneAndTwo || Two)
CallTwo();
if (OneAndThree || TwoAndThree || Three)
CallThree();
goto
is probably my 58th choice here...
1
+1 for suggesting polymorphism, though ideally that might simplify the client code down to just "Call();", using tell don't ask -- to push the decision logic away from the consuming client and into the class mechanism and hierarchy.
– Erik Eidt
5 hours ago
1
Proclaiming anything the best sight unseen is certainly very brave. But without additional info, I suggest a bit of scepticism and keeping an open mind. Perhaps it suffers from combinatorial explosion?
– Deduplicator
4 hours ago
Wow, I think this is the first time I've ever been downvoted for suggesting polymorphism. :-)
– user949300
4 hours ago
add a comment |
The best answer is use polymorphism.
Another answer, which, IMO, makes the if stuff clearer and arguably shorter:
if (One || OneAndTwo)
CallOne();
if (OneAndTwo || Two)
CallTwo();
if (OneAndThree || TwoAndThree || Three)
CallThree();
goto
is probably my 58th choice here...
The best answer is use polymorphism.
Another answer, which, IMO, makes the if stuff clearer and arguably shorter:
if (One || OneAndTwo)
CallOne();
if (OneAndTwo || Two)
CallTwo();
if (OneAndThree || TwoAndThree || Three)
CallThree();
goto
is probably my 58th choice here...
edited 5 hours ago
answered 5 hours ago
user949300user949300
5,52411426
5,52411426
1
+1 for suggesting polymorphism, though ideally that might simplify the client code down to just "Call();", using tell don't ask -- to push the decision logic away from the consuming client and into the class mechanism and hierarchy.
– Erik Eidt
5 hours ago
1
Proclaiming anything the best sight unseen is certainly very brave. But without additional info, I suggest a bit of scepticism and keeping an open mind. Perhaps it suffers from combinatorial explosion?
– Deduplicator
4 hours ago
Wow, I think this is the first time I've ever been downvoted for suggesting polymorphism. :-)
– user949300
4 hours ago
add a comment |
1
+1 for suggesting polymorphism, though ideally that might simplify the client code down to just "Call();", using tell don't ask -- to push the decision logic away from the consuming client and into the class mechanism and hierarchy.
– Erik Eidt
5 hours ago
1
Proclaiming anything the best sight unseen is certainly very brave. But without additional info, I suggest a bit of scepticism and keeping an open mind. Perhaps it suffers from combinatorial explosion?
– Deduplicator
4 hours ago
Wow, I think this is the first time I've ever been downvoted for suggesting polymorphism. :-)
– user949300
4 hours ago
1
1
+1 for suggesting polymorphism, though ideally that might simplify the client code down to just "Call();", using tell don't ask -- to push the decision logic away from the consuming client and into the class mechanism and hierarchy.
– Erik Eidt
5 hours ago
+1 for suggesting polymorphism, though ideally that might simplify the client code down to just "Call();", using tell don't ask -- to push the decision logic away from the consuming client and into the class mechanism and hierarchy.
– Erik Eidt
5 hours ago
1
1
Proclaiming anything the best sight unseen is certainly very brave. But without additional info, I suggest a bit of scepticism and keeping an open mind. Perhaps it suffers from combinatorial explosion?
– Deduplicator
4 hours ago
Proclaiming anything the best sight unseen is certainly very brave. But without additional info, I suggest a bit of scepticism and keeping an open mind. Perhaps it suffers from combinatorial explosion?
– Deduplicator
4 hours ago
Wow, I think this is the first time I've ever been downvoted for suggesting polymorphism. :-)
– user949300
4 hours ago
Wow, I think this is the first time I've ever been downvoted for suggesting polymorphism. :-)
– user949300
4 hours ago
add a comment |
IMO the root of the problem is that this piece of code shouldn't even exist.
You apparently have three independent conditions, and three independent actions to take if those conditions are true. So why is all that being funnelled into one piece of code that needs three Boolean flags to tell it what to do (whether or not you obfuscate them into an enum) and then does some combination of three independent things? The single responsibility principle seems to be having an off-day here.
Put the calls to the three functions where the belong (i.e. where you discover the need to do the actions) and consign the code in these examples to the recycle bin.
If there were ten flags and actions not three, would you extend this sort of code to handle 1024 different combinations? I hope not! If 1024 is too many, 8 is also too many, for the same reason.
So grateful for this answer! In my opinion the code is perfectly valid and genericized for this particular post. The question is in relation to thegoto
statement and not the concept of single responsibility. I have refactored the code to handle everything with four simpleif
statements. More to the point on your answer, there is nothing wrong with multiple if statements in the same method so long as they achieve a related goal to the method and simply alter the execution path. In my actual code each piece isn't actually a method call, but a single line execution.
– PerpetualJ
2 hours ago
1
As a point of fact, there are many well-designed APIs which have all kinds of flags, options, and assorted other parameters. Some may be passed on, some have direct effects, and yet others potentially be ignored, without breaking SRP. Anyway, the function could even be decoding some external input, who knows? Also, reductio ad absurdum often leads to absurd results, especially if the starting-point isn't even all that solid.
– Deduplicator
2 hours ago
add a comment |
IMO the root of the problem is that this piece of code shouldn't even exist.
You apparently have three independent conditions, and three independent actions to take if those conditions are true. So why is all that being funnelled into one piece of code that needs three Boolean flags to tell it what to do (whether or not you obfuscate them into an enum) and then does some combination of three independent things? The single responsibility principle seems to be having an off-day here.
Put the calls to the three functions where the belong (i.e. where you discover the need to do the actions) and consign the code in these examples to the recycle bin.
If there were ten flags and actions not three, would you extend this sort of code to handle 1024 different combinations? I hope not! If 1024 is too many, 8 is also too many, for the same reason.
So grateful for this answer! In my opinion the code is perfectly valid and genericized for this particular post. The question is in relation to thegoto
statement and not the concept of single responsibility. I have refactored the code to handle everything with four simpleif
statements. More to the point on your answer, there is nothing wrong with multiple if statements in the same method so long as they achieve a related goal to the method and simply alter the execution path. In my actual code each piece isn't actually a method call, but a single line execution.
– PerpetualJ
2 hours ago
1
As a point of fact, there are many well-designed APIs which have all kinds of flags, options, and assorted other parameters. Some may be passed on, some have direct effects, and yet others potentially be ignored, without breaking SRP. Anyway, the function could even be decoding some external input, who knows? Also, reductio ad absurdum often leads to absurd results, especially if the starting-point isn't even all that solid.
– Deduplicator
2 hours ago
add a comment |
IMO the root of the problem is that this piece of code shouldn't even exist.
You apparently have three independent conditions, and three independent actions to take if those conditions are true. So why is all that being funnelled into one piece of code that needs three Boolean flags to tell it what to do (whether or not you obfuscate them into an enum) and then does some combination of three independent things? The single responsibility principle seems to be having an off-day here.
Put the calls to the three functions where the belong (i.e. where you discover the need to do the actions) and consign the code in these examples to the recycle bin.
If there were ten flags and actions not three, would you extend this sort of code to handle 1024 different combinations? I hope not! If 1024 is too many, 8 is also too many, for the same reason.
IMO the root of the problem is that this piece of code shouldn't even exist.
You apparently have three independent conditions, and three independent actions to take if those conditions are true. So why is all that being funnelled into one piece of code that needs three Boolean flags to tell it what to do (whether or not you obfuscate them into an enum) and then does some combination of three independent things? The single responsibility principle seems to be having an off-day here.
Put the calls to the three functions where the belong (i.e. where you discover the need to do the actions) and consign the code in these examples to the recycle bin.
If there were ten flags and actions not three, would you extend this sort of code to handle 1024 different combinations? I hope not! If 1024 is too many, 8 is also too many, for the same reason.
edited 3 hours ago
answered 3 hours ago
alephzeroalephzero
28525
28525
So grateful for this answer! In my opinion the code is perfectly valid and genericized for this particular post. The question is in relation to thegoto
statement and not the concept of single responsibility. I have refactored the code to handle everything with four simpleif
statements. More to the point on your answer, there is nothing wrong with multiple if statements in the same method so long as they achieve a related goal to the method and simply alter the execution path. In my actual code each piece isn't actually a method call, but a single line execution.
– PerpetualJ
2 hours ago
1
As a point of fact, there are many well-designed APIs which have all kinds of flags, options, and assorted other parameters. Some may be passed on, some have direct effects, and yet others potentially be ignored, without breaking SRP. Anyway, the function could even be decoding some external input, who knows? Also, reductio ad absurdum often leads to absurd results, especially if the starting-point isn't even all that solid.
– Deduplicator
2 hours ago
add a comment |
So grateful for this answer! In my opinion the code is perfectly valid and genericized for this particular post. The question is in relation to thegoto
statement and not the concept of single responsibility. I have refactored the code to handle everything with four simpleif
statements. More to the point on your answer, there is nothing wrong with multiple if statements in the same method so long as they achieve a related goal to the method and simply alter the execution path. In my actual code each piece isn't actually a method call, but a single line execution.
– PerpetualJ
2 hours ago
1
As a point of fact, there are many well-designed APIs which have all kinds of flags, options, and assorted other parameters. Some may be passed on, some have direct effects, and yet others potentially be ignored, without breaking SRP. Anyway, the function could even be decoding some external input, who knows? Also, reductio ad absurdum often leads to absurd results, especially if the starting-point isn't even all that solid.
– Deduplicator
2 hours ago
So grateful for this answer! In my opinion the code is perfectly valid and genericized for this particular post. The question is in relation to the
goto
statement and not the concept of single responsibility. I have refactored the code to handle everything with four simple if
statements. More to the point on your answer, there is nothing wrong with multiple if statements in the same method so long as they achieve a related goal to the method and simply alter the execution path. In my actual code each piece isn't actually a method call, but a single line execution.– PerpetualJ
2 hours ago
So grateful for this answer! In my opinion the code is perfectly valid and genericized for this particular post. The question is in relation to the
goto
statement and not the concept of single responsibility. I have refactored the code to handle everything with four simple if
statements. More to the point on your answer, there is nothing wrong with multiple if statements in the same method so long as they achieve a related goal to the method and simply alter the execution path. In my actual code each piece isn't actually a method call, but a single line execution.– PerpetualJ
2 hours ago
1
1
As a point of fact, there are many well-designed APIs which have all kinds of flags, options, and assorted other parameters. Some may be passed on, some have direct effects, and yet others potentially be ignored, without breaking SRP. Anyway, the function could even be decoding some external input, who knows? Also, reductio ad absurdum often leads to absurd results, especially if the starting-point isn't even all that solid.
– Deduplicator
2 hours ago
As a point of fact, there are many well-designed APIs which have all kinds of flags, options, and assorted other parameters. Some may be passed on, some have direct effects, and yet others potentially be ignored, without breaking SRP. Anyway, the function could even be decoding some external input, who knows? Also, reductio ad absurdum often leads to absurd results, especially if the starting-point isn't even all that solid.
– Deduplicator
2 hours ago
add a comment |
Thanks for contributing an answer to Software Engineering Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f385901%2favoiding-the-goto-voodoo%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
5
there is no big debate. no one uses goto. make your enum a flag
– Ewan
6 hours ago
2
@Ewan Hence there is a big debate; there are scenarios where
goto
should be used, but in modern code it's usually for obfuscation purposes.– PerpetualJ
5 hours ago
1
it sounds like you want to have a big debate. But you'll need a better example of a good case to use goto. flag enum neatly solves this one, even if your if statement example wasnt acceptable and it looks fine to me
– Ewan
5 hours ago
@Ewan I'm here to avoid using it and am looking for alternatives (a fantastic one has already been offered), but to since you stated I'd need a better example; the current post is a good example since
C#
doesn't allow fall-through in theswitch
structure likeC
,C++
, andJava
. This is per the documentation over on MSDN; however, I believe we are getting off topic at this point.– PerpetualJ
5 hours ago
1
@Ewan No one uses the goto. When is the last time you looked at the Linux kernel source code?
– John Douma
2 hours ago