Switch case goes to default except one case - c#

when i tried to use the Switch case function, it goes always to the default message besides case 5:
private void btnCandlesLight_Click(object sender, EventArgs e)
{
int result;
result = Convert.ToInt32(textBox1.Text);
switch(result)
{
case 1:
day1.Start();
candlesOne();
break;
case 2:
day2.Start();
candlesTwo();
break;
case 3:
day3.Start();
candlesThree();
break;
case 4:
day4.Start();
candlesFour();
break;
case 5:
day5.Start();
candlesFive();
break;
case 6:
day6.Start();
candlesSix();
break;
case 7:
day7.Start();
candlesSeven();
break;
case 8:
day8.Start();
candlesEight();
break;
default:
MessageBox.Show("Enter new day");
break;
}
}
When I Enter the value 1 for example to the text box, the default case works, but only when I enter the value 5 it works perfectly.
If you want to see the difference between the function "candlesOne" to "candlesFive":
The "c" variable is a variable of the seconds. i tried to use a timer in a way of lighting up the candles every 2-3 seconds.
public void candlesOne()
{
firedmatch.Left = firedmatch.Left + 100;
if (c == 1)
{
candle1.Visible = true;
}
if (c == 3)
{
candle2.Visible = true;
}
}
and:
public void candlesFive()
{
firedmatch.Left = firedmatch.Left + 100;
if(c == 1)
{
candle1.Visible = true;
}
if(c == 3)
{
candle2.Visible = true;
}
if(c == 5)
{
candle3.Visible = true;
}
if(c == 7)
{
candle4.Visible = true;
}
if(c == 11)
{
candle5.Visible = true;
}
}
I haven't found a mistake,
can you guys help me?
Thanks

Have you checked if you really get for example (int)1 as a result of the "1" input from your conversion?
On a broader scale, there is a lot of repetition in your code, you should consider refactoring it a little.
In your CandlesOne and CandlesFive methods, you use a c variable, no idea what that is or where it comes from. Those two methods (and probably the other CandlesXXX() do the same kind of things. Can't you remove complexity by generalizing the logic? Can the result used in your switch-case be passed as a parameter and used to trigger the numbers of c == X calls in the CandleXXX() methods?
This way you could remove the switch and lose a lot of complexity!
Edit
If you have further problems, consider creating a .NET Fiddle, I miss a lot of context in your code so I cannot efficiently help you here.
Some refactoring ideas for you:
// Somewhere else in your code, create a dictionary with your day1-day8 objects
var days = new Dictionary<int, Day>()
days[1] = day1;
...
days[8] = day8;
//Simplfiy your method
private void btnCandlesLight_Click(object sender, EventArgs e)
{
try
{
var dayIndex = Convert.ToInt32(textBox1.Text);
if(dayIndex > 0 && dayIndex <= 8)
{
days[dayIndex].Start(); //Get the corresponding day via its Key
LightUpCandles(dayIndex); //pass the key as a parameter
}
else
{
MessageBox.Show("Enter new day");
}
}
catch(InvalidCastException exception)
{
//Whatever you do when the textbox cannot be parsed
}
}
I still don't get what your candlesOne to five methods are really doing or why the method "candlesOne" lights up two candles (pay attention to the variable naming). I also don't get how this makes up some kind of timer... but here's a first potential refactoring for it anyway:
public void LightUpCandles(int dayIndex)
{
firedmatch.Left = firedmatch.Left + 100;
if(c == 1)
{
candle1.Visible = true;
}
if(c == 3 && dayIndex > 1)
{
candle2.Visible = true;
}
if(c == 5 && dayIndex > 2)
{
candle3.Visible = true;
}
if(c == 7 && dayIndex > 3)
{
candle4.Visible = true;
}
if(c == 11 && dayIndex > 4)
{
candle5.Visible = true;
}
}

Your switch logic is correct which I tested with the following;
int result;
result = Convert.ToInt32(textBox1.Text);
switch (result)
{
case 1:
MessageBox.Show("1");
break;
case 2:
MessageBox.Show("2");
break;
case 3:
MessageBox.Show("3");
break;
case 4:
MessageBox.Show("4");
break;
case 5:
MessageBox.Show("5");
break;
case 6:
MessageBox.Show("6");
break;
case 7:
MessageBox.Show("7");
break;
case 8:
MessageBox.Show("8");
break;
default:
MessageBox.Show("Enter new day");
break;
}
If you don't get the same results I would perhaps look at making the message boxes above display the data type of the variable.
MessageBox.Show(result.GetType().ToString());

Related

Can you create a switch with multiple expressions?

I was wondering if I can use a switch with multiple expressions. For example:
string s = "A";
int i = 3;
switch (s, i)
{
case "A", 1:
//DoStuff
break;
case "A", 2:
//DoStuff
break;
case "A", 3:
//DoStuff
break;
...
}
I don't want to use hundreds of if(s == "A" && i == 1)-Statements so it would be great if there's a better solution.
PS: This switch is just an example, I'm actually using it with more complex strings like Names
You certainly can, for example by using tuples:
string s = "A";
int i = 3;
switch (s, i)
{
case ("A", 1):
// DoStuff.
break;
case ("A", 2):
// DoStuff.
break;
case ("A", 3):
// DoStuff.
break;
}
(Basically exactly what you typed, except with the addition of parenthesis in the cases to make them into tuples.)
Note that this requires C# 7 or later.
Since C# 7, it is possible to do the following:
string s = "A";
int i = 3;
switch (s)
{
case "A" when i == 1:
//DoStuff
break;
case "A" when i == 2:
//DoStuff
break;
case "A" when i == 3:
//DoStuff
break;
...
}

C# Days of the week tryparse string conversions

So I am currently trying to finish this program that when you input a number correlating to the days of the week, it reflects the text connected to the numeric variable. (IE : Sunday - 1, Monday - 2, etc etc.)
I have found a functioning code that makes the program work, but it outputs incorrect information. No matter what number I put in, it always displays Sunday. And it doesn't stop me from inputting bad variables. Which I want it to. I'm frustrated at this point and I am very new to all of this. Can someone check over my code and tell me what I'm doing incorrectly? Thank you.
private void OkButton_Click(object sender, EventArgs e)
{
string day ="1";
int number;
if (int.TryParse(day, out number))
{
if (number >= 7 && number <= 1)
{
switch (day)
{
case "1":
dayOutputLabel.Text = "Sunday";
break;
case "2":
dayOutputLabel.Text = "Monday";
break;
case "3":
dayOutputLabel.Text = "Tuesday";
break;
case "4":
dayOutputLabel.Text = "Wednesday";
break;
case "5":
dayOutputLabel.Text = "Thursday";
break;
case "6":
dayOutputLabel.Text = "Friday";
break;
case "7":
dayOutputLabel.Text = "Saturday";
break;
}
}
else
{
MessageBox.Show("Invalid number input. Please use a number between 1 and 7.");
}
}
else
{
MessageBox.Show("Please put in a valid number.");
}
}
private void ExitButton_Click(object sender, EventArgs e)
{
this.Close();
}
Looks like you've hard coded day = "1" (i.e. Sunday).
Also this is a mistake:
if (number >= 7 && number <= 1)
Surely you meant...
if (number >= 1 && number <= 7)
I can't tell precisely what sort of project you're working on, but the following slight modification works in wpf and should be all you need to solve this:
private void OKButton_Click(object sender, RoutedEventArgs e)
{
string day = myTextBox.Text.Trim();
int number = 0;
if (int.TryParse(day, out number))
{
if (number >= 1 && number <= 7)
{
switch (day)
{
case "1":
dayOutputLabel.Content = "Sunday";
break;
case "2":
dayOutputLabel.Content = "Monday";
break;
case "3":
dayOutputLabel.Content = "Tuesday";
break;
case "4":
dayOutputLabel.Content = "Wednesday";
break;
case "5":
dayOutputLabel.Content = "Thursday";
break;
case "6":
dayOutputLabel.Content = "Friday";
break;
case "7":
dayOutputLabel.Content = "Saturday";
break;
}
}
else
{
MessageBox.Show("Invalid number input. Please use a number between 1 and 7.");
}
As mentioned in the comment above... here is a possible solution using the System.DayOfWeek enumeration:
private void OKButton_Click(object sender, RoutedEventArgs e)
{
// this TryParse makes use of pattern matching
if(int.TryParse(myTextBox.Text.Trim(), out var input) && input >= 0 && input <= 6)
{
// this should automatically convert to the name of the day of week
// if not, add .ToString() at the end
dayOutputLabel.Content = (DayOfWeek)input;
}
else
{
MessageBox.Show(
text: "Please use a number between 0 and 6",
caption: "Invalid Input",
buttons: MessageBoxButtons.OK,
icon: MessageBoxIcon.Error);
}
}
And here is an another option using Enum.TryParse() instead:
private void OKButton_Click(object sender, RoutedEventArgs e)
{
// this TryParse makes use of pattern matching
if(Enum.TryParse(myTextBox.Text.Trim(), out DayOfWeek input) &&
input >= DayOfWeek.Sunday && input <= DayOfWeek.Saturday)
{
// this should automatically convert to the name of the day of week
// if not, add .ToString() at the end
dayOutputLabel.Content = input;
}
else
{
MessageBox.Show(
text: "Please use a number between 0 and 6",
caption: "Invalid Input",
buttons: MessageBoxButtons.OK,
icon: MessageBoxIcon.Error);
}
}

How to minimize this switch?

switch(number){
case 2:
a+=b;
break;
case 3:
a+=b;
break;
case 4:
a+=b;
d=f;
break;
case 5:
d=e;
break;
}
how to minimize first three switch cases which which does similar work?
If you using C# 7, you can make use of Pattern Matching, even though this is an overkill as rightly pointed by Jon Skeet. But in case, you want to stick to switch case, and want to reduce 'case', you could do the following
switch(number)
{
case var _ when number == 2 || number==3 || number==4:
a+=b;
if(number ==4)
d=f
break;
case 5:
d=e;
break;
}
You can also replace the first case with variants like
case var _ when new[]{2,3,4}.Contains(number):
Or
case var _ when number >= 2 || number <= 3: // As pointed by earlier answer
Without pattern matching, you could do the following as well
switch(number)
{
case 2:
case 3:
case 4:
a+=b;
if(number ==4)
d=f;
break;
case 5:
d = e;
break;
}
Btw, if your problem is "a+b" is about 60 lines of code, you always have the option to make it a function (and move it out of switch case) to increase its readability.
switch(number)
{
case 2:
case 3:
case 4:
MethodAbAction();
if(number ==4)
MethodDFAction();
break;
case 5:
MethodDEAction();
break;
}
btw, a 60 line method is never fun to read. It would be better if you can split up.
if (2 <= number && number <= 4) {
a += b;
}
if (number == 4) {
d = f;
} else if (number == 5) {
d = e;
}
if (number != 5)
{
a += b;
}
if (number == 4)
{
d = f;
}
else
if (number == 5)
{
d = e;
}

CheckListBox Updated from another CheckListBox

I'm creating a form with two Checklistboxes. The first one is populated by a database query, while the latter is dinamically created when I check elements on the first one and these ones have to be replicated on the second one. The first works fine, while the second give me troubles, since it returns me always n-1 elements. I tried unsucessfully several methods, for instance BeginUpdate() and EndUpdate(), cblStaff..GetItemChecked(i)) instead of cblStaff.GetItemCheckState(i).Equals(CheckState.Checked).
I guess it's a matter of value refresh since I placed a label (lblCounter) to check how many items on cblStaff have been selected.
Maybe it's a matter of events, and I'm using the wrong one, but I'm getting crazy with this control.
This is the code:
private void cblStaff_ItemCheck(object sender, ItemCheckEventArgs e)
{
cblStaff.BeginUpdate();
switch (e.CurrentValue)
{
case CheckState.Indeterminate:
e.NewValue = CheckState.Checked;
break;
case CheckState.Checked:
e.NewValue = CheckState.Unchecked;
persons--;
break;
case CheckState.Unchecked:
e.NewValue = CheckState.Checked;
persons++;
break;
}
cblStaff.EndUpdate();
TeamUpdate();
}
private void RefreshDirector()
{
cblDirector.Items.Clear();
int counter = 0;
for (int i = 0; i < cblStaff.Items.Count; i++)
{
if (cblStaff.GetItemCheckState(i).Equals(CheckState.Checked)) {
cblDirector.Items.Add(cblStaff.Items[i].ToString(), CheckState.Unchecked);
counter++;
lblCounter.Text = "" + counter;
}
}
}
private void TeamUpdate()
{
switch (persons) {
case 0:
lblTeam.Text = "No team";
break;
case 1:
lblTeam.Text = "1 person team";
break;
default:
lblTeam.Text = "" + persons + " people team";
break;
}
cblStaff.Refresh();
RefreshDirector();
}

Listbox unassigned variable

Full disclosure here, I am a student doing homework. I have 2 listboxes with items that can be selected. What is said in them is not needed to be extracted. I wrote the code out and everything works except I get an error saying "use of unassigned variable" on 3 variables at the end of the code. They are locFees, days, and registration. Can anyone tell me what I am doing wrong that is causing the variables to not have a value?
private void btnCalc_Click(object sender, EventArgs e)
{
double registration, lodging, total, days, locFees;
int workshopIndex, locationIndex;
if (lbWorkshop.SelectedIndex != -1)
{
workshopIndex = lbWorkshop.SelectedIndex;
switch (workshopIndex)
{
case 0:
days = 3;
registration = 1000;
break;
case 1:
days = 3;
registration = 800;
break;
case 2:
days = 3;
registration = 1500;
break;
case 3:
days = 5;
registration = 1300;
break;
case 4:
days = 1;
registration = 500;
break;
}
}
else
{
MessageBox.Show("You didn't select a workshop.");
}
if (lbLocation.SelectedIndex != -1)
{
locationIndex = lbLocation.SelectedIndex;
switch (locationIndex)
{
case 0:
locFees = 150;
break;
case 1:
locFees = 225;
break;
case 2:
locFees = 175;
break;
case 3:
locFees = 300;
break;
case 4:
locFees = 175;
break;
case 5:
locFees = 150;
break;
}
}
else
{
MessageBox.Show("You didn't select a city.");
}
lodging = locFees * days;
total = registration + lodging;
}
Can anyone tell me what I am doing wrong that is causing the variables to not have a value?
Sure - you're ignoring the possibility that workshopIndex isn't 0, 1, 2, 3 or 4.
If you believe that should never happen, just add:
default:
throw new InvalidOperationException("Invalid selected index " + workshopIndex);
Or if you just want to use some defaults, do something like:
default:
days = 1;
registration = 100;
break;
That's the first way you can end up with days and registration unassigned.
Next, there's the fact that you only go into the switch block at all if lbWorkshop.SelectedIndex != -1. Your else block is just:
else
{
MessageBox.Show("You didn't select a workshop.");
}
... so after that else block, you're going to continue. You probably want:
else
{
MessageBox.Show("You didn't select a workshop.");
return;
}
You've then got the same problem for locFees, in terms of both the switch statement and the else block.
One thing to learn from this: be grateful that the compiler spotted these for you. It's stopped you from running code which definitely had bugs in. That's always a good thing.

Categories