Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
Let's make it easier. In this case return at the end have squigglies. What should I type in the return at the end to receive VK_F2 as a return value from the method?
internal uint AssignStartShortcut()
{
switch (currentStartValue)
{
case "F2":
return VK_F2;
}
return;// how this should look?
}
If I don't use return after swith then I have message: not all code paths return value.
Your error most likely is:
Compiler Error CS0165
Use of unassigned local variable 'name'
The C# compiler does not allow the use of uninitialized variables. If
the compiler detects the use of a variable that might not have been
initialized, it generates compiler error CS0165. For more information,
see Fields. Note that this error is generated when the compiler
encounters a construct that might result in the use of an unassigned
variable, even if your particular code does not. This avoids the
necessity of overly-complex rules for definite assignment.
Easy fix, initialize it:
internal uint AssignStopShortcut()
{
uint stopNumber = 0;
switch (currentStartValue)
...
Or make sure the static analyser knows that it can't fall through (i.e it is always initialized)
uint stopNumber;
switch (currentStartValue)
{
case "F3":
stopNumber = VK_F3;
return stopNumber; //squigly lines below
default:
// no other options
throw new InvalidOperationException("Bazzinga!");
}
Or even better, just return the constant, don't use the local variable.
internal uint AssignStopShortcut()
{
switch (currentStartValue)
{
case "F3":
return VK_F3; //squigly lines below
default:
throw new InvalidOperationException("Bazzinga!");
}
}
Adding to the TheGeneral's solution, your problem is that you need to initialise the variable.
internal uint AssignStartShortcut()
{
uint startNumber = 0; //initialise variable
if (currentStartValue == "F2")
{
startNumber = VK_F2;
}
return startNumber; //value of 0 is returned if the IF statement conditon is not met.
}
From your comment to TheGenral's proposed solution as I cannot yet make comments, is that since the initialised variable is set to Zero in this case and you are only doing a check for a particular value and if that condition is not met then "startNumber" won't be updated with "VK_F2" or "VK_F3" values. Therefore, that's why the Switch statement default case is met as the "currentStartValue" had not met any of the cases.
For example if you wanted to check for all cases, it should look something like this:
internal uint AssignStopShortcut()
{
uint stopNumber = 0; //initialise this variable is a must if it's to be declared in this method.
switch (currentStartValue)
{
case "F1": break;
case "F2": break;
case "F3":
stopNumber = VK_F3;
break;
case "F4": break;
case "F5": break;
case "F6": break;
case "F7": break;
case "F8": break;
default:
// no other options
throw new InvalidOperationException("Bazzinga!");
}
return stopNumber;
}
Hope this helps.
Thanks to all of you guys for your help. Problem solved and it wasn't in if or switch statement. Turns out data that should be passed simply wasn't. My bad. Thanks again.
Related
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")
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I have an enum inside a class called cConstsAndEnums:
public class cConstsAndEnums
{
public enum EnSelectedKtovet
{
En_KtovetMaam = 1,
En_KtovetTmg
};
}
In other class I have switch:
switch (dr["rowSelectedKtovet"].ToString())
{
case cConstsAndEnums.EnSelectedKtovet.En_KtovetMaam:
doSomthing;
break;
default:
}
The problem is that I'm getting an error:
Cannot implicitly convert type 'cConstsAndEnums.EnSelectedKtovet' to 'string'.
I try to do:
case (string)cConstsAndEnums.EnSelectedKtovet.En_KtovetMaam:
but I have error:
Cannot convert type 'cConstsAndEnums.EnSelectedKtovet' to 'string'.
Tried also:
case Convert.ToString(cConstsAndEnums.EnSelectedKtovet.En_KtovetMaam):
but again I have error:
A constant value is expected.
Please help.
Thanks.
The reason is the data type of the switch (string) is different to your cases (enum values). Trying to solve this by using .ToString() means you are doing an operation, but a case needs always a constant value. Do it the other way and cast the string to the enum before using it at the switch.
cConstsAndEnums.EnSelectedKtovet enumValue = (cConstsAndEnums.EnSelectedKtovet)
Enum.Parse(typeof(cConstsAndEnums.EnSelectedKtovet, dr["rowSelectedKtovet"].ToString());
switch (enumValue)
{
case cConstsAndEnums.EnSelectedKtovet.En_KtovetMaam:
...
}
Also think about to store the numeric value of the enumeration instead of the string value. Every enum literal has a value which you can simply cast to an integer:
EnSelectedKtovet enumValue = EnSelectedKtovet.En_KtovetMaam;
int storedEnumValue = (int)enumValue;
EnSelectedKtovet restoredEnumValue = (EnSelectedKtovet)storedEnumValue;
With this solution you dont need to deal with any string, which is much more safe and comfortable.
You should use Enum.Parse() method (in case if you ensure that string has always prvoded enum value) or Enum.TryParse() (in case if string cuold have anything, so you can set your enum to default value)
In your case try this:
var myEnum = (EnSelectedKtovet)Enum.Parse(typeof(EnSelectedKtovet), dr["rowSelectedKtovet"].ToString());
switch (myEnum)
{
case EnSelectedKtovet.En_KtovetMaam:
doSomthing;
break;
default:
}
In your switch statement, convert it to the enum
switch(Enum.Parse(typeof(EnSelectedKtovet), dr["rowSelectedKtovet"].ToString()){
case cConstsAndEnums.EnSelectedKtovet.En_KtovetMaam:
doSomthing;
break;
default:
}
switch ((EnSelectedKtovet)int.Parse(dr["rowSelectedKtovet"].ToString()))
{
case EnSelectedKtovet.En_KtovetMaam:
break;
default:
break;
}
I hope it will work for you.
This is a case of the XY Problem. You are asking about your attempted solution, not the actual problem.
In this case the actual problem is that you read an enum value from the database. The index method returns an object so you can't compare it with anything else directly. You'd have to cast it to an int (if the database returns an int) or a string. You can cast it to an enum directly too, since enums are basically named integers.
Instead of that, you tried to convert it to a string. When you tried to compare that string to the enum values, you got a compilation error because obviously an enum isn't a string.
If the underlying field value is an integer, you can just cast it to the enum's type:
var value=(cConstsAndEnums.EnSelectedKtovet)dr["rowSelectedKtovet"];
switch (value)
{
case cConstsAndEnums.EnSelectedKtovet.En_KtovetMaam:
doSomthing;
break;
default:
}
If it's a string that contains the enum name, you'll have to parse the string with Enum.Parse or Enum.TryParse
var fieldValue=(string)dr["rowSelectedKtovet"];
var value=Enum.Parse(typeof(cConstsAndEnums.EnSelectedKtovet),fieldValue);
switch (value)
...
With a bit of C# 7 and pattern matching magic, you could match both cases:
var value=dr["rowSelectedKtovet"];
switch(value)
{
case int val when Enum.IsDefined(typeof(cConstsAndEnums.EnSelectedKtovet),val) :
var enumValue=(cConstsAndEnums.EnSelectedKtovet)val;
//Use enumValue
break;
case string s when Enum.TryParse<cConstsAndEnums.EnSelectedKtovet>(s,out var enumValue):
//Use enumValue
break;
default :
throw new ArgumentException($"Unknown {value}");
}
You Can try.ToString("D") to compare with Enum value.
string selectedValue= dr["rowSelectedKtovet"].ToString();
if(selectedValue==cConstsAndEnums.EnSelectedKtovet.En_KtovetMaam.ToString("D"))
{
doSomthing();
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
i'm making simple name generator, and it's working like that: I got an array with name values it's 4 elements, and i'm using random class to pick specific name from array, and next i'm using switch case to validate which one is picked and print it to console.
But, it's only 4 element, but what when i'll try to make 100 elements 4example? I've tried to make switch case in for loop to increment everything in one case, but it turns out that case index should be const. Well, is there any other possible way to make switch case more flexible, and smaller?
Here's code for intersed http://pastebin.com/bbCxLtRq
There is no switch needed:
if (NameIndex >= 0 && NameIndex <= 3)
{
return Name[NameIndex];
}
return null;
With more complex examples, you can use return to get rid of break.
Instead of
switch (NameIndex)
{
case 0:
name = Name[0];
break;
case 1:
name = Name[1];
break;
case 2:
name = Name[2];
break;
case 3:
name = Name[3];
break;
}
return name;
write
switch (NameIndex)
{
case 0:
return Name[0];
case 1:
return Name[1];
case 2:
return Name[2];
case 3:
return Name[3];
}
return null;
As mentioned in the comments, there is NO need for Switch statement to achieve this goal - refer to the following code snippet as an example:
public class Generate
{
static string[] Name = new string[] { "Mariusz", "Janusz", "Bogdan", "Zbigniew" };
static Random random = new Random();
public static string NameGen()
{
return Name[(int) random.Next(3)];
}
}
In case you really need to use Switch statement (for some reason, may be just for didactic purpose), then there is a way to simplify it like shown in the following snippet:
switch (NameIndex)
{
case 0:
case 1:
case 2:
case 3:
return Name[NameIndex];
}
Hope this may help
Make your methods independents of a fixed length:
public static string NameGen()
{
int index = random.Next(Names.Length);
return Names[index];
}
public static string SurnameGen()
{
int index = random.Next(Surnames.Length);
return Surnames[index];
}
This question already has answers here:
Variable declaration in a C# switch statement [duplicate]
(7 answers)
odd variable scope in switch statement
(4 answers)
Closed 9 years ago.
So if I have a switch with 3 cases, each case has duplicate local variables declared in them. You would think that the variables would be local to that case so you should be able to use the same name repeatedly. However, this doesn't appear to be the 'case'.
Apparently the other case blocks can see the variables in each other.
Okay, no big deal right? Except that when you try and access that variable that it can obviously see, it says it can't see it???
int index = list.SelectedIndex;
switch(index){
case(0):
bool val = true; //First declaration s'allll good
if(val) //No issues here either obviously
MessageBox.Show("Huh?");
break;
case(1):
bool val = true; //Says it already exists??
if(val)
MessageBox.Show("Huh?");
break;
case(2):
bool val3 = true; //Change the variable name so you can use it however,
if(val) //When you try to access the val in case 0 it says it doesn't exist?????
MessageBox.Show("Huh?");
break;
}
Is there an obvious syntax fold in space time I am missing here?
The variables, in the IL, are defined to the scope of the switch, so you can't reuse them in the other case statements because it would redefine them.
Likewise, you still have to define the variables for each case (i.e. you've seen how even if one case has the variable the others can't actually leverage its definition).
The better approach, for you, is to define val outside the switch.
Since cases are just labels, there's no scoping between cases -- they can see variables on the highest scope of the case, hence collisions on your val.
You can either move bool val outside of the switch, or you can enclose the cases in braces to scope it yourself, i.e.
case(0):
{
bool val = true;
if (val)
MessageBox.Show("Huh?");
}
break;
Variables in a switch statement are scoped to the entire switch statement. See this MSDN page at the bottom "The scope of a local variable or constant declared in a switch block is the switch block.".
To get around this, you can either declare the variable above the switch statement or (less cleanly) declare it a single time and re-use throughout the switch statement like so.
int index = list.SelectedIndex;
switch(index){
case(0):
bool val = true; //First declaration s'allll good
if(val) //No issues here either obviously
MessageBox.Show("Huh?");
break;
case(1):
val = true; //Declared in case 0
if(val)
MessageBox.Show("Huh?");
break;
case(2):
val = true; //Still declared from case 0
if(val)
MessageBox.Show("Huh?");
break;
}
The following extract of code is failing to compile resulting in not code paths return a value. Both types Test1StandardChargeCalculator and Test2StandardChargeCalculator are derived from the return type.
I know how to fix this, but my question is why should I have to? A bool is a value type - hence can only represent true or false, both of which are catered for in this snippet. So why the failed compilation?
internal StandardChargeCalculator Create()
{
bool value = true;
switch (value)
{
case true:
return new Test1StandardChargeCalculator();
case false:
return new Test2StandardChargeCalculator();
}
} //not all code paths return a value
When using a switch statement, the compiler does not understand that when you are using a boolean type to switch on there can only be two results.
The error occurs because you do not have a default case.
Don't use a switch for boolean test - use an if statement:
bool value = true;
if(value)
{
return new Test1StandardChargeCalculator();
}
return new Test2StandardChargeCalculator();
Why do you think the compiler should special-case boolean and detect that all possible values have a case statement?
If you were writing a compiler, would you invest development effort and increase the risk of bugs by implementing this?
In Absence of evidence is not evidence of absence Eric Lippert writes about the limitations of 'proofing' that a variable is unassigned and the weaker aim of the compiler in this regard:
that we're not interested in proving for certain that x is unassigned.
We're interested in proving for certain that x is assigned! If we can
prove that for certain, then x is "definitely assigned". If we cannot
prove that for certain then x is "not definitely assigned".
Which does not directly explain this example but note that it is the same issue as :
int x;
if (a < 10)
x = 0;
else if (a >= 10)
x = 1;
y = x; // x is 'unassigned'
We can quickly see that x will always be assigned, the compiler does not even attempt to find out.
To my understanding it is inconsistant to the definition of the switch which says:
If no case expression matches the switch value, then control is transferred to the statement(s) that follow the optional default label. If there is no default label, control is transferred outside the switch.
You are right: there should be no compiler error. So, this might be a case where no answer is the answer. You will have to live with it.
switch (answer)
{
...
default:
return "It is as it is"
}
Maybe better solution would be
internal StandardChargeCalculator Create()
{
StandardChargeCalculator result = null;
bool value = true;
switch (value)
{
case true:
result = new Test1StandardChargeCalculator();
break;
case false:
result = new Test2StandardChargeCalculator();
break;
}
return result;
}