How add "or" in switch statements? - c#

This is what I want to do:
switch(myvar)
{
case: 2 or 5:
...
break;
case: 7 or 12:
...
break;
...
}
I tried with "case: 2 || 5" ,but it didn't work.
The purpose is to not write same code for different values.

By stacking each switch case, you achieve the OR condition.
switch(myvar)
{
case 2:
case 5:
...
break;
case 7:
case 12:
...
break;
...
}

You do it by stacking case labels:
switch(myvar)
{
case 2:
case 5:
...
break;
case 7:
case 12:
...
break;
...
}

You may do this as of C# 9.0:
switch(myvar)
{
case 2 or 5:
// ...
break;
case 7 or 12:
// ...
break;
// ...
}

case 2:
case 5:
do something
break;

Case-statements automatically fall through if you don't specify otherwise (by writing break). Therefor you can write
switch(myvar)
{
case 2:
case 5:
{
//your code
break;
}
// etc...
}

The example for switch statement shows that you can't stack non-empty cases, but should use gotos:
// statements_switch.cs
using System;
class SwitchTest
{
public static void Main()
{
Console.WriteLine("Coffee sizes: 1=Small 2=Medium 3=Large");
Console.Write("Please enter your selection: ");
string s = Console.ReadLine();
int n = int.Parse(s);
int cost = 0;
switch(n)
{
case 1:
cost += 25;
break;
case 2:
cost += 25;
goto case 1;
case 3:
cost += 50;
goto case 1;
default:
Console.WriteLine("Invalid selection. Please select 1, 2, or3.");
break;
}
if (cost != 0)
Console.WriteLine("Please insert {0} cents.", cost);
Console.WriteLine("Thank you for your business.");
}
}

Since C# 8 there are switch expressions that are better readable: no case, : and break;/return needed anymore. Combined with C# 9's logical patterns:
static string GetCalendarSeason(DateTime date) => date.Month switch
{
3 or 4 or 5 => "spring",
6 or 7 or 8 => "summer",
9 or 10 or 11 => "autumn",
12 or 1 or 2 => "winter",
_ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
};
Limitation: with this syntax, at the right of the => you cannot use curly braces ({ and }) for statements.

Related

Memory game doesn't open all cards upon starting

I'm making a memory game in C#. It has 10 pairs of cards, total 20. It's supposed to work like this: When pressing the Start button, the game shuffles randomly the cards and reveals all cards. After 3 seconds it flips them. Then, the player has to find all pairs.
I'm having a problem with shuffling. I wrote this code. It's being executed when I press the Start button:
foreach (String icon in icons)
{
int x1 = r.Next(1, 21);
int x2 = r.Next(1, 21);
if (!num.Contains(x1))
{
num.Add(x1);
}
else
{
do
{
x1 = r.Next(1, 21);
} while (!num.Contains(x1));
num.Add(x1);
}
if (!num.Contains(x2))
{
num.Add(x2);
}
else
{
do
{
x2 = r.Next(1, 21);
} while (!num.Contains(x2));
num.Add(x2);
}
switch (x1)
{
case 1:
pictureBox1.Image = Image.FromFile(icon);
break;
case 2:
pictureBox2.Image = Image.FromFile(icon);
break;
case 3:
pictureBox3.Image = Image.FromFile(icon);
break;
case 4:
pictureBox4.Image = Image.FromFile(icon);
break;
case 5:
pictureBox5.Image = Image.FromFile(icon);
break;
case 6:
pictureBox6.Image = Image.FromFile(icon);
break;
case 7:
pictureBox7.Image = Image.FromFile(icon);
break;
case 8:
pictureBox8.Image = Image.FromFile(icon);
break;
case 9:
pictureBox9.Image = Image.FromFile(icon);
break;
case 10:
pictureBox10.Image = Image.FromFile(icon);
break;
case 11:
pictureBox11.Image = Image.FromFile(icon);
break;
case 12:
pictureBox12.Image = Image.FromFile(icon);
break;
case 13:
pictureBox13.Image = Image.FromFile(icon);
break;
case 14:
pictureBox14.Image = Image.FromFile(icon);
break;
case 15:
pictureBox15.Image = Image.FromFile(icon);
break;
case 16:
pictureBox16.Image = Image.FromFile(icon);
break;
case 17:
pictureBox17.Image = Image.FromFile(icon);
break;
case 18:
pictureBox18.Image = Image.FromFile(icon);
break;
case 19:
pictureBox19.Image = Image.FromFile(icon);
break;
case 20:
pictureBox20.Image = Image.FromFile(icon);
break;
}
switch (x2)
{
case 1:
pictureBox1.Image = Image.FromFile(icon);
break;
case 2:
pictureBox2.Image = Image.FromFile(icon);
break;
case 3:
pictureBox3.Image = Image.FromFile(icon);
break;
case 4:
pictureBox4.Image = Image.FromFile(icon);
break;
case 5:
pictureBox5.Image = Image.FromFile(icon);
break;
case 6:
pictureBox6.Image = Image.FromFile(icon);
break;
case 7:
pictureBox7.Image = Image.FromFile(icon);
break;
case 8:
pictureBox8.Image = Image.FromFile(icon);
break;
case 9:
pictureBox9.Image = Image.FromFile(icon);
break;
case 10:
pictureBox10.Image = Image.FromFile(icon);
break;
case 11:
pictureBox11.Image = Image.FromFile(icon);
break;
case 12:
pictureBox12.Image = Image.FromFile(icon);
break;
case 13:
pictureBox13.Image = Image.FromFile(icon);
break;
case 14:
pictureBox14.Image = Image.FromFile(icon);
break;
case 15:
pictureBox15.Image = Image.FromFile(icon);
break;
case 16:
pictureBox16.Image = Image.FromFile(icon);
break;
case 17:
pictureBox17.Image = Image.FromFile(icon);
break;
case 18:
pictureBox18.Image = Image.FromFile(icon);
break;
case 19:
pictureBox19.Image = Image.FromFile(icon);
break;
case 20:
pictureBox20.Image = Image.FromFile(icon);
break;
}
There is also an auxiliary list "num" and a list "icons", which contains the names of the icons' files.
List<int> num = new List<int>();
List<String> icons = new List<String>() { "agelada.png", "elefantas.png", "gata.png", "gatopardos.png", "kamilopardali.png", "liontari.png", "lykos.png", "skylos.png", "tigris.png", "zebra.png" };
This code is supposed to work like this:
~It generates two random numbers, from 1 to 20 (the game has 20 cards), and stores them into x1 and x2 respectively.
~For each icon, member of the "icons" list: If x1 isn't found in the list num, it gets added in it. If x1 is found, a new number is being generated, until generating one that isn't in "num". Then it gets stored in "num". Same for x2. This process repeats for all the member of the list "icons".
~Then, depending of the randomly generated numbers, the icon gets inserted into the respective pictureBoxes, for example, if the numbers are 6 and 17, the picture is entered into pictureBox6 and pictureBox17.
The goal of this process is to make sure that all 10 pictures are displayed exactly twice, to make pairs.
However, I have a problem. When I click on Start, not all cards are flipped (The question mark is the "back side" of the cards). It looks like this:
Picture
It's supposed to show animal pictures in all cards.
Any ideas?
In addition to the recommendations around managing the PictureBox controls in arrays, I would recommend you change the line (not shown) where you create the Random object to something like this:
Random r = new Random(10);
Setting the seed like this while you're debugging will let you predict the output, and as you step through code from one run to the next run, it's easier to follow what's happening.
That said, if you stepped through this code:
do
{
x1 = r.Next(1, 21);
} while (!num.Contains(x1));
num.Add(x1);
If you stopped the code on adding the value to your array, you would have seen the value already exists in the array, which is the opposite of the intended action. That means your loop is exiting at the wrong time.
In this case, it's because your check is the opposite logic of what it should be, you want to keep running through this loop while the value is in the array. In other words, changing both loops to look like this:
do
{
x1 = r.Next(1, 21);
} while (num.Contains(x1));
num.Add(x1);
You will end up filling up your array with 20 unique values.

C# Switch statement scenario

UPDATED:
Is there a way to accomplish what the code below attempts to do (doesn't pass syntax because case 2 and case 3 can't have duplicate declarations and/or because num can't be 2 and 3 at the same time)?
var num = 0;
switch (num)
{
case 1:
//do stuff applicable to 1 only;
break;
case 2:
//do stuff applicable to 2 only;
break;
case 3:
//do stuff applicable to 3 only;
break;
case 2:
case 3:
//do stuff applicable to 2 and 3 only;
break;
}
The question is confusingly posed. I think what you want is to have a case that runs for two, a case that runs for three, and a case that runs for two-or-three.
Just use two switches:
switch (num)
{
case 1: One(); break;
case 2: Two(); break;
case 3: Three(); break;
}
switch (num)
{
case 2:
case 3: TwoOrThree(); break;
}
Or
switch (num)
{
case 1: One(); break;
case 2:
case 3:
switch (num)
{
case 2: Two(); break;
case 3: Three(); break;
}
TwoOrThree();
break;
}
Or duplicate the code:
switch (num)
{
case 1: One(); break;
case 2: Two(); TwoOrThree(); break;
case 3: Three(); TwoOrThree(); break;
}
I would NOT recommend un-duplicating the code like this:
switch (num)
{
case 1: One(); break;
case 2: Two(); goto twoOrThree; break;
case 3: Three(); twoOrThree: TwoOrThree(); break;
}
Yuck.
not with a single-level switch (or a nasty GOTO). A switch can only execute one case. A better solution would be a nested if (or switch) within the 2/3 case:
switch (num)
{
case 1:
//do stuff applicable to 1 only
break;
case 2:
case 3:
if(num == 2)
{
//do stuff applicable to 2 only
}
if(num == 3)
{
//do stuff applicable to 3 only
}
//do stuff applicable to 2 OR 3
break;
}
It's as simple as this...
switch (value)
{
case 1:
// Do 1 stuff
break;
case 2:
case 3:
// We can use an if-else construct here given that there's only two possibilities.
if (value == 2)
{
// 2 only stuff here
}
else
{
// 3 only stuff here
}
// Do anything applicable to BOTH here, or above the if construct, depending on your requirements.
break;
default:
// Any other stuff here
break;
}
Or just use an if construct, which is arguably cleaner (switch is really only intended for simple many to one logical mappings)...
if (value == 1)
{
// 1 stuff
}
else if (value == 2 || value == 3)
{
if (value == 2) {
// 2 stuff only
}
else
{
// 3 stuff only
}
// 2 or 3 stuff, or above the if construct above, if you require.
}
else
{
// Anything else here
}
Or simply...
switch (value)
{
case 1:
OneStuff();
break;
case 2:
TwoStuff();
TwoOrThreeStuff();
break;
case 3:
ThreeStuff();
TwoOrThreeStuff();
break;
default:
AnythingElse();
}
And wrap what you need to do for each of the above in separate methods.
The third method would be my preference here. It's cleaner and easier to debug than using complex mixtures of switch and if.
You could just use if statements instead
var num = 0;
if(num == 1)
{
// do stuff applicable to 1 only
}
else if(num == 2)
{
// do stuff applicable to 2 only
}
else if(num == 3)
{
// do stuff applicable to 3 only
}
if(num == 2 || num == 3)
{
// do stuff applicable to 2 AND 3
}
Or as a switch and an if
switch (num)
{
case 1:
// do stuff applicable to 1 only
break;
case 2:
// do stuff applicable to 2 only
break;
case 3:
// do stuff applicable to 3 only
break;
}
if(num == 2 || num == 3)
{
// do stuff applicable to 2 AND 3
}
You could use the goto case statement and have a unique identifier for combined operations in case 2 and 3. Make sure that that is never hit by any other number:
var num = 0;
var text = "";
switch (num)
{
case 1:
text = "do stuff applicable to 1 only";
break;
case 2:
text = "do stuff applicable to 2 only";
goto case 23;
case 3:
text = "do stuff applicable to 3 only";
goto case 23;
case 23:
text = "do stuff applicable to 2 AND 3";
break;
}
The use of goto is not recommended in general but it is common to use it in switch-statements and situations like that.

c# Switch issue. Homework

This is what I have so far. My problem is that none of the cases are responding when you enter either the correct or incorrect answer. I'm not really sure where to go from here. The program asks you answer two random numbers being multiplied. And then it should give you one of the eight responses.
int result = 0;
int caseSwitch = 0;
string question = DoMultiplication(out result);
Console.WriteLine(question);
int answer = Convert.ToInt32(Console.ReadLine());
if (answer == result)
{
switch (caseSwitch)
{
case 1:
Console.WriteLine("Very Good");
break;
case 2:
Console.WriteLine("Excellent");
break;
case 3:
Console.WriteLine("Nice Work");
break;
case 4:
Console.WriteLine("Keep up the good work!");
break;
}
}
else
{
switch (caseSwitch)
{
case 1:
Console.WriteLine("No, Please Try Again.");
break;
case 2:
Console.WriteLine("Wrong, Try Once More");
break;
case 3:
Console.WriteLine("Don't Give Up!");
break;
case 4:
Console.WriteLine("No, Keep Trying!");
break;
caseSwitch is always 0, so your switch will always fall through without writing anything to console.
If you want a random response you could do something like this:
int result = 0;
int caseSwitch = new Random().Next(1, 4);
string question = DoMultiplication(out result);
Console.WriteLine(question);
int answer = Convert.ToInt32(Console.ReadLine());
if (answer == result)
{
switch (caseSwitch)
{
case 1:
Console.WriteLine("Very Good");
break;
case 2:
Console.WriteLine("Excellent");
break;
case 3:
Console.WriteLine("Nice Work");
break;
case 4:
Console.WriteLine("Keep up the good work!");
break;
}
}
else
{
switch (caseSwitch)
{
case 1:
Console.WriteLine("No, Please Try Again.");
break;
case 2:
Console.WriteLine("Wrong, Try Once More");
break;
case 3:
Console.WriteLine("Don't Give Up!");
break;
case 4:
Console.WriteLine("No, Keep Trying!");
break;
CaseSwitch is always = 0.
You need to assign a value to it, and-or add a default case to your switch.
You have your int caseSwitch = 0; and I don't see you changing it in your code to any of 1-4. So what do you expect it to do if you dont have the caseSwitch changed...

Add a additional condition to Case Statement in Switch

Is it possible to add a additional Condition to Switch Statement like below in C#
switch(MyEnum)
{
case 1:
case 2:
case 3 && Year > 2012://Additional Condtion Here
//Do Something here..........
break;
case 4:
case 5:
//Do Something here..........
break;
}
In above mentioned example if MyEnum = 3 then it has to be excuted if Year > 2012... Is it possible?
[EDITED]
Year > 2012 is not applicable to case 1 & case 2.
C#7 new feature:
case...when
https://learn.microsoft.com/en-us/dotnet/articles/csharp/whats-new/csharp-7
public static int DiceSum4(IEnumerable<object> values)
{
var sum = 0;
foreach (var item in values)
{
switch (item)
{
case 0:
break;
case int val:
sum += val;
break;
case IEnumerable<object> subList when subList.Any():
sum += DiceSum4(subList);
break;
case IEnumerable<object> subList:
break;
case null:
break;
default:
throw new InvalidOperationException("unknown item type");
}
}
return sum;
}
In order for it to work the way you've indicated with the fallthrough logic for 1 and 2, I'd suggest moving the //do something here portion out to a method or function and then doing this:
case 1:
case 2:
DoSomething();
break;
case 3:
if(Year > 2012) { DoSomething(); }
break;
The other alternative would be:
case 1:
case 2:
case 3:
if (MyEnum != 3 || Year > 2012) {
// Do something here
}
break;
but I think the first option is much more intuitive and readable.
The answer is no.
You'll need the following:
switch (MyEnum)
{
case 1:
case 2:
DoSomething();
break;
case 3:
if (Year > 2012) DoSomething();
break;
}
You can't add condition to a case. Case clause has to be a compile time constant. Instead you can use an if statement inside the case statement.
case 3:
if( > 2012)
{
//Do Something here..........
}
break;
You have to use the if condition inside your case , you can't use && in case statement, use like below:
switch(MyEnum)
{
case 1:
case 2:
case 3: //Additional Condtion Here
if (Year > 2012)
{
//Do Something here..........
}
break;
case 4:
case 5:
//Do Something here..........
break;
}
Or, alternatively, you can add the condition to the switch:
switch (MyEnum!=3 || Year>2012 ? MyEnum : -1)
{
case 1:
case 2:
case 3:
//Do Something here..........
break;
case 4:
case 5:
//Do Something here..........
break;
}
Most of the time, I do something like that...
(sorry for the naming, the use case didn't inspire me)
Considering those private classes:
private class NumberState
{
public static NumberState GetState(int number, int year)
{
if (number == 1)
return new FirstNumberState();
if (number == 2)
return new FirstNumberState();
if (number == 3 && year > 2012)
return new FirstNumberState();
if (number == 4)
return new SecondNumberState();
if (number == 5)
return new SecondNumberState();
return new DefaultNumberState();
}
}
private class FirstNumberState : NumberState { }
private class SecondNumberState : NumberState { }
private class DefaultNumberState : NumberState { }
Then you can do:
switch (NumberState.GetState(MyEnum, Year))
{
case FirstNumberState _:
// do something
break;
case SecondNumberState _:
// do something
break;
case DefaultNumberState _:
default:
throw new Exception("Unhandled number state");
}
It's easy to read even when your conditions get more complicated.
You can use C# 8 feature
public static bool SomeHelper(int value)
=> value switch
{
100 => true,
var x when x >= 200 && x <= 300 => true,
_ => false, // All other values
};
You will have true with values 100, 200...300 and false with other values
Also you can use params:
public static bool SomeHelper(int value, bool param)
=> value switch
{
100 => true,
var x when x >= 200 && x <= 300 && param => true,
_ => false, // All other values
};
in this case you will have true only if value is 100 and param is false

Switch-Case don't work like this?

I am trying to convert a JavaScript switch to a C# one.
I am getting error Error 3 Cannot implicitly convert type 'bool' to 'int'
switch (numero)
{
case (numero > -1 && numero < 16):
rtn = list1[numero] + " " + str2;
if (primerDigito != 1)
{
rtn += "s";
}
break;
case (numero > 15 && numero < 30):
if (numero != 20)
{
rtn = list2[primerDigito] + list1[segundoDigito];
}
else
{
rtn = "veinte";
}
rtn += " " + str2 + "s";
break;
case (numero > 29 && numero < 100):
rtn = list2[primerDigito] + "nta";
if (segundoDigito != 0)
{
rtn += " y " + list1[segundoDigito];
}
rtn += " " + str2 + "s";
break;
case 100:
rtn = "cien " + str2 + "s";
break;
default:
rtn = "número invalido";
}
Is there a work around for this?
Note: I really MUST use switch-case (and not if-elses)
You cannot do this: a switch statement can only use single values, not ranges for the cases.
You need an if/else tree instead. Something in the form of:
if(numero > -1 && numero < 16) {
rtn = list1[numero] + " " + str2;
if (primerDigito != 1)
{
rtn += "s";
}
} else if(numero > 15 && numero < 30) {
// logic in second block
} else if...
Note that if you're absolutely, totally committed to using a switch, you would have to enumerate all of the cases (but this is such an egregious sin against software engineering that I can't even believe I'm writing it out - do not do this, it's just an example of how switch statements work):
switch(numero)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
rtn = list1[numero] + " " + str2;
if (primerDigito != 1)
{
rtn += "s";
}
break;
case 16:
...
case 28:
case 29:
// second logic block
break;
...
}
If I saw this in my codebase, though, I would be baffled and angry.
The answer, although not the one you want, is that you have to use compile-time constants in your case expressions. If the expression will vary at run-time then you must use if..else instead.
In addition, the case value is an implicit logical equality comparison and can't make use of < or >.
This is (mostly) not possible without using an if-else. If you MUST use a switch, then this is the only way I know of (letting the cases drop down to each other):
switch (numero)
{
case 0:
case 1:
case 2:
...
case 15:
//Do Stuff
break;
case 16:
...
//Continue as above for each range
}
Unfortunately there is no ranges support in switch statements, you can either use if else statements or you can do this:
case 15:
case 16:
case 16:
case 18:
// do something
Nope, this isn't how switch/case works. if/else if is the right thing to do.
You can stack cases as shown below, but when you have this many cases it is NOT the right thing to do.
switch(numero)
{
case 0:
case 1:
case 2:
and so on
case 15:
code here
break;
case 16:
case 17:
and so on
case 29:
code here
break;
and so on
case 100:
rtn = "cien " + str2 + "s";
break;
default:
rtn = "número invalido";
}
Yes you are entirely correct. Switch statements in C# dont work like that.
The correct way to implement such logic in C# is to use an if, else if, else block. (Yes I have seen your note but am unsure why you must use a switch).
For various design reasons switch statements and if else chains are discouraged because by their very definition they have X behaviours or responsibilities. A better approach is to try for a solution that uses polymorphism. You should aim to refactor these behaviours into separate distinct classes that each handle one of the cases.

Categories

Resources