Switch Statement with Enum - Or (||) and (&&) - c#

I'm making a project and I have a question. I have 3 enum states like this:
enum GameLevel
{
Level1,
Level2,
None,
}
There's a part in my code where I want to check if there's any level selected or none, so I wanted to do something like:
case !GameLevel.None
or
case GameLevel.Level1 || GameLevel.Level2
Is This Possible?

Various options:
Use switch with a default:
switch (level)
{
case GameLevel.None:
// Whatever
break;
default:
// Do something else
// break
}
Use switch with explicit cases:
// Note: if you add a Level3, you'd need to change this...
switch (level)
{
case GameLevel.Level1:
case GameLevel.Level2:
// Whatever
break;
}
Use an if statment:
if (level != GameLevel.None)
{
...
}

Switch is not used to get a "its not the case"-case. However you can use the default: case, which always executes, when the other cases are "false".
For your !GameLevel.None better use an if case. if(selectedGameLevel != GameLevel.None) { }

I believe the choice of assignment should be based on how many levels you plan on implementing. For less levels (as shown in your example), I would use if and else if as opposed to using switch. Switch only works better if there are more options, as it is then performed differently for faster execution. Jon Skeet's answer will guide you on how to implement the choice you make.

Related

c# Using enum in Switch Case throwing exception

I am working on .NET 6.0 application, I have enum that I am trying to use in switch as to compare with string value but getting exception.
error
private static bool ValidateAlphanumericCase(string text, string fieldName)
{
if (!string.IsNullOrWhiteSpace(fieldName))
{
var rule = GetRule(fieldName).TxtFieldFormat; // string value
switch (rule)
{
case TextFieldFormat.AlphanumericUpperCase.ToString():
break;
case TextFieldFormat.AlphanumericLowerCase.ToString():
break;
}
}
else
{
new EmptyFieldNameException();
}
return false;
}
enum
public enum TextFieldFormat
{
AlphanumericUpperCase = 0,
AlphanumericLowerCase = 1,
}
TextFieldFormat.AlphanumericUpperCase.ToString()
This is a method invocation expression and it is not a valid pattern for swith statement.
You can find all valid patterns here: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns
The closest pattern is type pattern or constant pattern, I guess the compiler recognizes AlphanumericUpperCase as a nested class of TextFieldFormat and fails.
In this case you can use nameof operator.
switch (rule)
{
case nameof(TextFieldFormat.AlphanumericUpperCase):
break;
case nameof(TextFieldFormat.AlphanumericLowerCase):
break;
}
Seems you understood switch-case block a little bit different.
A switch block is simply a shortcut (but more performant shortcut) of many if - else if - else blocks.
Of course they are not the same, but their working logic almost the same.
With this very little info, you can easily think about what's wrong in your code.
Bingo, you're right! Case blocks should check the state. (Boolean value..Just interests with either the given statement results true or false..)
After checking the boolean result, Which case's statement match, code continues on that case block.
So, in your situation your code could be like this :
switch (rule)
{
/// Some statements need to put in paranthesis. Also you would need put business codes of cases into curly braces.
/// I write from my mind.
/// So please try paranthesis and/or braces if this code break.
case rule==TextFieldFormat.AlphanumericUpperCase.ToString():
DoSomethingWithFirstCase(); break;
case rule==TextFieldFormat.AlphanumericLowerCase.ToString():
DoSomethingWitSecondCase(); break;
default: DoSomethingWhenNoMatchWithOtherCases();
}
Hope this helps.
You can also use it this way
TextFieldFormat.AlphanumericUpperCase.ToString("g" or "G")

How to use a variable into a "case" of a switch case

I'm a beginner in C# and I'm developing an HMI (WinForms).
I have a DataGridView filled with data and some column with buttons.
When I click on a button of the column, the CellContentClick event is triggering and I would like to get the precise column where the user clicked, using a switch case:
(simplified code)
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
var senderGrid = (DataGridView)sender;
if (senderGrid.Columns[e.ColumnIndex] is DataGridViewButtonColumn && e.RowIndex >= 0) // if cell button
{
switch (e.ColumnIndex)
{
case Column1.Index: // <- not building because Column1.Index is a variable
// do something
break;
case Column2.Index:
// do something
break;
//etc
default: break;
}
}
}
The problem is that ColumnX.Index can not be put into the case condition because it's a variable. Of course, I could use directly the number of the column index, but since I'm developing and always moving the columns, I would like to keep the ColumnX.Index way.
Switches cannot have dynamic evaluated statements in the case statement. They must be statically evaluated.
Below post explain it why :
C# switch statement limitations - why?
Also you can use alternative ways, as explained in below link:
Is there a better alternative than this to 'switch on type'?
Depending on what you need in your particular case, you could also make use of "Tag" property of the column (it's on DataGridViewBand that is base for DataGridViewColumn). When I worked with forms I used to place there operation code that the button is supposed to trigger.
So on the column you place for example Tag="UpdateRecord" and in the code you can have
switch (column.Tag as string)
{
case "UpdateRecord":
// Update code
break;
// Other cases
}
This way you can easily reorder columns of your grid without playing with fixing those switches.
Also (as the next step towards cleaner code) you could put "UpdateRecord" text into const in some class and use it in column definition and switch definition.
You'll need to use something else - an else or else if statement could work for you. You could also use an enum of the expected value and reference them in your case statement.
I'd like to keep the switch case method
Well, you can abuse pattern matching:
switch (c.ColumnIndex)
{
case int i when i == Column1.Index:
// do something
break;
case int i when i == Column2.Index:
// do something
break;
//etc
default: break;
}
but I would not recommend.

Preventing If within If functions (or cases)

I'm building a code where I have to go trough alot of if/case functions. This on itself is not really a problem only that alot of these if's are the kinda the same.
In my code it has to go trough an if function, and if there is a match it wont matter what match it is it will have to go trough the same next if. But depending on both answers it will have to go to a different part of the code.
So for exmaple:
Switch(A){
case 1:
Switch(B){
case 1: do11thing();
case 2: do12thing();
}
case 2:
Switch(B){
case 1: do21thing();
case 2: do22thing();
}
}
Does anyone know a solution instead of having to place the Switch(B) a lot of times within my code.
In case you have more jumps than executable code (the case that happens quite often when programming state machines), you may store your logic in some nested Dictionary, List and/or array object like the following:
// Maps A and B values to functionality
var funcs = new[] {
new[] { func00, func01, func02, ... },
new[] { func10, func11, func12, ... },
new[] { func20, func21, func22, ... },
...
};
// Actually runs functionality according to your mapping
funcs[A][B](params);
So, in case of A=1 and B=2, the func12 will be called.
Of course, you may use lambdas (params) => {} as funcs in the structure.
you can use one if for the function returning value 2 , and then inside this if use all possibilities as different switch cases.It will be smoother and faster than multiple if loops.
for ex :-
if (2 == function1) {
switch(value of function 2)
{
case value_1:
..//do whatever u want;
break;
case value_2:
..//do whatever u want;
break;
default:
//do some error handling;
break;
}
}
One thing you can do is combine cases. For example, say you have a string value that's your outer switch variable, and an int that's the inner switch variable. Your original code might be:
switch (theString)
{
case "Foo":
switch (theInt)
{
case 1: DoThing1(); break;
case 2: DoThing2(); break;
// many other cases
}
DoFooThing();
break;
case "Bar":
switch (theInt)
{
case 1: DoThing1(); break;
case 2: DoThing2(); break;
// other cases, same as with "Foo"
}
DoBarThing();
break;
}
You can combine the cases and have a conditional:
switch (theString)
{
case "Foo":
case "Bar":
switch (theInt)
{
case 1: DoThing1(); break;
case 2: DoThing2(); break;
// many other cases
}
if (theString == "Foo")
DoFooThing();
else
DoBarThing();
break;
}
The type of logic you're describing, especially if there are very many cases, is probably best implemented using a lookup table. Doing so makes it much easier to follow the logic. It takes a bit more time to set up, but you can easily see in the table that you construct exactly what will happen with any combination of input values.

using switch statements with constants or enumerations? (Which is better)? C#

HI, I've got a simple question, but one that has been bugging me for a while.
Question:
When using switch statements in C#, is it considered better practice to use enums over constants or vice versa? Or is it a matter of preference? I ask this because many people seem to like using enums, but when you are switching on an int value, you have to cast each of the values contained in the enum to an int, even if you specify the type of enum.
Code Snippet:
class Program
{
enum UserChoices
{
MenuChoiceOne = 1,
MenuChoiceTwo,
MenuChoiceThree,
MenuChoiceFour,
MenuChoiceFive
}
static void Main()
{
Console.Write("Enter your choice: ");
int someNum = int.Parse(Console.ReadLine());
switch (someNum)
{
case (int)UserChoices.MenuChoiceOne:
Console.WriteLine("You picked the first choice!");
break;
// etc. etc.
}
}
}
Is there some way you can create an instance of the enum and just cast the whole enum to an int?
Thanks!
Why not do this instead?
UserChoices choice = (UserChoices)int.Parse(Console.ReadLine());
switch (choice)
{
case UserChoices.MenuChoiceOne:
// etc...
Then you only need to cast once.
Update: fixed bug in code!
I think the preference of enums over constants is because of readability and not because of performance. I find it easier to read enums in code (in general and not just in switch statements), than to read/understand constants and their usage.
and btw, you don't have to cast every case, you can just cast your switch.
switch((UserChoices)someEnum)
{
...
I believe you can simply do:
switch((UserChoices)someNum)
{
case UserChoices.MenuChoiceOne:
break;
default:
throw Exception // whatever here
}

C# switch/break

It appears I need to use a break in each case block in my switch statement using C#.
I can see the reason for this in other languages where you can fall through to the next case statement.
Is it possible for case blocks to fall through to other case blocks?
Thanks very much, really appreciated!
Yes, you can fall through to the next case block in two ways. You can use empty cases, which don't need a break, or you can use goto to jump to the next (or any) case:
switch (n) {
case 1:
case 2:
case 3:
Console.WriteLine("1, 2 or 3");
goto case 4;
case 4:
Console.WriteLine(4);
break;
}
The enforcement of "break" is there to stop bugs. If you need to force a fall-thru then use "goto case " (replace the with appropriate value)
the following example shows what you can do:
switch(n)
{
case 1:
case 2:
//do something for 1+2
//...
goto case 3;
case 3:
//do something for 3, and also extra for 1+2
//...
break;
default:
//do something for all other values
//...
break;
}
See http://msdn.microsoft.com/en-us/library/06tc147t%28VS.80%29.aspx
C# doesn't support implicit fall through construct, but the break (or goto) nonetheless has to be there (msdn). The only thing you can do is stack cases in the following manner:
switch(something) {
case 1:
case 2:
//do something
break;
case 3:
//do something else
}
but that break (or another jump statement like goto) just needs to be there.
In my C# (.NET 1.1, CF) code, both of these are allowed:
switch (_printerChoice)
{
case BeltPrintersEnum.ZebraQL220:
return new ZebraQL220Printer();
break;
case BeltPrintersEnum.ONeal:
return new ONealPrinter();
break;
default:
return new ZebraQL220Printer();
break;
}
switch (_printerChoice)
{
case BeltPrintersEnum.ZebraQL220:
return new ZebraQL220Printer();
case BeltPrintersEnum.ONeal:
return new ONealPrinter();
default:
return new ZebraQL220Printer();
}
...but with the breaks in, they are grayed out, so considered moot. So, at least in my case, they are allowed but not required.

Categories