This question already has answers here:
Switch case in C# - a constant value is expected
(9 answers)
Closed 5 years ago.
I'm having a problem here.
void Sre_Reconhecimento(object sender, SpeechRecognizedEventArgs e)
{
string text = System.IO.File.ReadAllText(#"C:\Users\ADMIN25\Desktop\testing.txt");
string[] words = text.Split(',');
switch (e.Result.Text)
{
case words[0]:
MessageBox.Show("works!");
break;
case words[1]:
MessageBox.Show("works too!");
break;
}
}
When I'm trying to run the program, I get this error: A constant value is expected.
How can I fix it without using if/elseif case?
You should do this with if / else.
However, if for some reason you really want to use a switch, you can sort of do it with pattern maching.
e.g.
void Main()
{
string[] words = {"Foo", "Bar", "Quax"};
var word = "Bar";
switch(word)
{
case string w when w == words[0]:
MessageBox.Show($"word was {words[0]}");
break;
case string w when w == words[1]:
MessageBox.Show($"word was {words[1]}");
break;
}
}
Really though, use if / else here. I don't think switch is appropriate for this type of use case.
You cant use a switch statement dynamically like this, because its expects a constant value at compile time
However
You can use a collection of if statements,
You could also use a dictionary of Action
Exmaple
dict = new Dictionary<string, Action>()
{
{"Standard", CreateStudySummaryView},
{"By Group", CreateStudySummaryByGroupView},
{"By Group/Time", CreateViewGroupByHour}
};
dict[value].Invoke();
Related
This question already has an answer here:
Switch with ToLower() causes error CS0426 The type name '' does not exist in the type ''
(1 answer)
Closed 1 year ago.
Can someone explain this error to me, I just don't get how it thinks there's a type involved
var header = "ABCDEfooGHIJ";
switch (true)
{
case header.Contains("foo"): //error here
return true;
case header.Contains("bar"): //and here
return false;
}
Error = 'header' is a variable but is used like a type
switch (true) isn't a "thing" in C# like it's VB counterpart (Select True) . And even if it was, I'd strongly recommend avoiding it.
When you write a switch statement in C#, the cases must either be a constant or a pattern match. If you are insistent on using a switch, you can use the following (which only works on C# 7+)
switch (header)
{
case var _ when header.Contains("foo"):
return true:
case var _ when header.Contains("bar"):
return false:
default:
throw new Exception();
}
In this case, var _ is the object pattern (which will match anything non-null) along with a discard since we want to operate on the other variable. Don't like the discard? You could do this as well:
switch (header)
{
case var h1 when h1.Contains("foo"):
return true:
case var h2 when h2.Contains("bar"):
return false:
default:
throw new Exception();
}
That said, don't use a switch for this. A chain of if/else is much more clear. Anyone reading your code (including your future self) will thank you for it.
if (header.Contains("foo"))
return true;
if (header.Contains("bar"))
return false;
// etc
So i am new to programming so im pretty confused about this. I created an array and tried to use it inside of a switch statement:
string[] General = new string[5];
{
General[0] = "help";
General[1] = "commands";
General[2] = "hello";
General[3] = "info";
General[4] = "quit";
}
switch(General)
{
case 0:
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine("This is a new program. Therefore the amount of commands are limited. \nIt can do simple things. For example, if you say 'tell the time' then it will tell the time\n");
Console.ForegroundColor = oldColor;
continue;
}
}
As far as i am aware there are no problems with this. However, when i run the code i am greeted with this error : "A switch expression or case label must be a bool, char, string, integral, enum, or corresponding nullable type"
I am genuinely stuck with this and i cant find any answers on the internet so any help will be greatly appreciated. Thanks
It sounds like what you are looking for is an enum.
public enum General {
help = 0,
commands = 1,
hello = 2,
info = 3,
quit = 4
}
Then you can use a switch statement just fine :).
// variable to switch
General myGeneral;
// myGeneral is set to something
switch(myGeneral)
{
case General.help:
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine("This is a new program. Therefore the amount of commands are limited. \nIt can do simple things. For example, if you say 'tell the time' then it will tell the time\n");
Console.ForegroundColor = oldColor;
break;
}
You are doing the switch statement on the entire array, opposed to a single entry in the array.
Assuming you are trying to write all of the available inputs you could do
string[] General = new string[5];
{
General[0] = "help";
General[1] = "commands";
General[2] = "hello";
General[3] = "info";
General[4] = "quit";
}
foreach(var option in General)
{
switch(option)
{
case "help":
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine("This is a new program. Therefore the amount of commands are limited. \nIt can do simple things. For example, if you say 'tell the time' then it will tell the time\n");
Console.ForegroundColor = oldColor;
break;
}
case "commands":
{
//Do some stuff
break;
}
//etc etc
}
}
The parameter in the switch statement should be the user input, not your optional values, for example:
int input = 0; // get the user input somehow
switch (input)
{
case 0:
{
// Do stuff, and remember to return or break
}
// Other cases
}
Also, this is a perfect use case for an Enum. That would look something like this:
public enum General
{
HELP = 0,
COMMANDS = 1,
HELLO = 2,
INFO = 3,
QUIT = 4
}
int input = 0; // get the user input somehow
switch (input)
{
case General.HELP: //Notice the difference?
{
// Do stuff, and remember to return or break
}
// Other cases
}
This makes your intention very clear, and therefore makes your code more readable and more maintainable. You can't do this with your array, because even though you declare your array in your code, it is still variable and therefore its state at the switch statement is not known at compile time. Enums are immutable, and therefore their values are known at compile time and can be used in switch statements.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
What is the best alternative for a if --else if --block that contains many if statements.
code:
string word="";
if(letter=='a')
{
// do some action
call(a);
}
else if (letter=='b')
{
call(b)
}
else if (letter=='c')
{
call(c)
}
else if (letter=='d')
{
// do some action
call(d)
}
else if (letter=='e')
{
// do some action
call(e)
}
................
..............
else if (letter=='z')
{
// do some action
call(z)
}
If there are many if-else statements what is the best way to find a solution for such a scenario. Is there a way to effectively design such a scenario using classes/objects?
I am sure many of us would have faced such problems like this during design/coding. Is there a effective way to handle such a situation?
NO SWITCH STATEMENTS PLEASE. AN EFFECTIVE DESIGN ALGORITHM USING C# OBJECTS WOULD BE THE BEST BET.
In C# the most direct translation is a switch statement. While switch is not strictly speaking an object-oriented construct, char is not a proper object in C# either.
switch(letter)
{
case 'a':
call(a);
break;
case 'b':
call(b);
break;
// and so on
}
If the parameter is not a simple value type but rather an object, use a virtual method instead of an explicit control structure. This is the true "object oriented" way to do it: in Smalltalk, ifTrue:, ifFalse: and ifTrue:ifFalse: are methods on Boolean taking code blocks as parameters! C# makes this rather verbose, though.
static class Example {
static void Sample(ISpeaker input) {
input.Speak(); // this call acts like a control structure
}
}
interface ISpeaker {
void Speak();
}
class Cat : ISpeaker {
public void Speak() {
Console.WriteLine("Meow");
}
}
class Dog : ISpeaker {
public void Speak() {
Console.WriteLine("Woof");
}
}
If you are stuck with a simple type, another approach is an explicit dispatch table.
static readonly Dictionary<char, Action> dispatch
= new Dictionary<char, Action> {
{ 'a', () => call(a) },
{ 'b', () => call(b) },
};
static void Process(char letter) {
dispatch[letter]();
}
If your conditions are too complex for a Dictionary-based dispatch table, you can use a List-based linear dispatch table which more closely mirrors the behavior of else-if chains:
static List<KeyValuePair<Func<char, bool>, Action>> dispatch
= new List<KeyValuePair<Func<char, bool>, Action>>() {
{ x => x == 'a', () => call(a) },
{ x => x == 'b', () => call(b) },
{ x => true, () => callDefault() },
};
static void Process(char letter) {
dispatch.First(kvp => kvp.Key(letter)).Value();
}
You can do the following:
private Dictionary<char, Action> _dic =
new Dictionary<char, Action>
{
{'a', (Action)a},
{'b', (Action)b},
...
};
And then
var action = this._dic.TryGetValue(letter);
if (action == null)
{
// this is like default case - no key matched the letter
}
else
{
// call the action associated with the letter
action();
}
https://msdn.microsoft.com/en-us/library/06tc147t.aspx
Do you mean a switch? This is effectivly like a large list of else-ifs
Use switch as an alternative to if...else.
switch offers more readability of your code and is more easy to understand rather that if else where, if you are nesting heavily, it might get difficult to understand and read code.
Also, switch is slightly better on the performance side when compared to if...else.
Hope this helps.
Technically, you picked a more complex way to express a switch statement. Switch statements, in turn, may be considered a "code smell".
If I understand your example correctly, you really only want to vary a parameter on a method call based on the value of some variable. There might not be any good way to improve upon writing your code as switch statement, but maybe using a Dictionary to look up the parameter based on the letter value is an option to consider.
You can use a switch statement.
switch (letter)
{
case 'a':
case(a);
break;
case 'b':
case(b);
break;
...
case 'z':
case(z);
break;
default:
Assert.Fail(letter.ToString() + " was an unexpected value");
break;
}
Use a switch statement:
switch(value)
{
case value == "X":
// handle
break;
case ...
break;
default:
// Doesn't match any case above
break:
}
I am calling a function that has a type declared against the method, ie.
public T Get<T>().
I read in a string from a file and parse this through a switch to determine the type used, ie.
switch (type)
{
case "Text":
item = Get<Text>();
break;
case "Button":
item = Get<Button>();
break;
}
How would I then go about returning the item of Type from the function where it was called? Note that I don't want to return a common parent as I need access to the methods of the derived class.
public <????> newGet()
{
switch (type)
{
case "Text":
item = Get<Text>();
break;
case "Button":
item = Get<Button>();
break;
}
return item;
}
Using dynamic sounds like a bad idea. You should reconsider what you're doing here.
"Note that I don't want to return a common parent as I need access to the methods of the derived class."
OK, so... you're going to do what to access these methods? Use another switch to switch between the types and then call the methods you want? Why are there two switch statements here doing the same thing? I don't know the exact architecture of what you're dealing with, but generally you'd be better off finding out what type you're going to be getting back (i.e. by returning "Text" or "Button" or whatever from a function) and then calling a strongly-typed function which goes and gets the thing and calls methods on it.
You can consider using the dynamic type. It's only available for .NET 4.0 and above
public dynamic newGet(string type)
{
dynamic item = null;
switch (type)
{
case "Text":
item = "ABC";
break;
case "Number":
item = 1;
break;
}
return item;
}
As you can see, I can use the Length of the string returned from newGet
dynamic text= newGet("Text");
Console.WriteLine(text.Length); //"ABC".Length = 3
dynamic number= newGet("Number");
Console.WriteLine(number + 5); //1 + 5 = 6
This can also works. Just be careful of runtime exception
string text= newGet("Text"); //You can assign to
Console.WriteLine(text.Length); //"ABC".Length = 3
int number= newGet("Number");
Console.WriteLine(number + 5); //1 + 5 = 6
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
Consider this code:
if (results.Contains(14))
{
//anything
}
else if (results.Contains(15))
{
//anything
}
else if (results.Contains(16))
{
//anything
}
I want write this code with switch case :
switch (results)
{
case results.Contains(14):
}
But we can't write this in C#.
What is the clear way for write the above code, knowing that results is a long[]?
What's wrong with this:
if (results.Contains(14) || results.Contains(15) || results.Contains(16))
{
new Exception("anything");
}
since it is probably in a string that has that number one solution would be to use a regular expression.
var m = System.Text.RegularExpressions.Regex.Matches(results, #"\d{1,2}")[0];
throw new Exception(m);
(NOTE: I did this in notepad so it might require a small tweak)
You will have to probably play with the match syntax as this is only good for 1-2 numbers. in a string.
What are you really trying to do?
The following should work, but I am not sure if that's what you had in mind:
int[] values = {14, 15, 16};
foreach (var n in values) {
if(result.Contains(n))
throw new Exception(n.ToString())
}
-- EDIT: the question has changed considerably so here's an update --
I would probably use plain if-else but if you have many options or complex logic (e.g. not just results.Contains()), sometimes it is better to choose tables:
int[] results = {13, 14, 15};
action_map = new Dictionary<int, Action>();
action_map[14] = () => Console.Out.WriteLine("14");
action_map[15] = () => Console.Out.WriteLine("15");
action_map[16] = () => { throw new InvalidOperationException(); };
action_map[0] = () => {}; // NOP, default case - executed if no match found
var action_key = dict.Keys.FirstOrDefault(k => results.Contains(k));
action_map[action_key]();
In real code, I would probably wrap it into a class:
var table = new FnTable();
table.Add(14, () => Console.Out.WriteLine("14"));
table.Add(15, () => Console.Out.WriteLine("15"));
table.Add(16, () => { throw new InvalidOperationException(); });
int[] results = {13, 14, 15};
table.ExecuteFirstFrom(results);
Usually a clear way to replace if/switch statements is to use polymorphism. However, in the example you've provided the if statements are so trivial, that they can be replaced by a simple algorithm which calculates the contents of the exception, as stated in Robert Snyder's answer.
I like approach with action dictionaries
var swticher = new Dictionary<long, Func<Exception>>()
{
{15,()=>new Exception("15")},
{14,()=>new Exception("14")}
};
throw swticher[14].Invoke();
Of course more complex examples will show power of this approach :)
Why to use dictionaries instead of switches: https://stackoverflow.com/a/11617459/1714342
Abstract:
The short answer is that the switch statement executes linearly, while
the dictionary executes logarithmically.
You can use a switch statement inside a foreach:
long[] results = new long[] { 15, 14, 16 };
foreach (long v in results)
{
switch (v)
{
case 14:
// anything
break;
case 15:
// anything
break;
case 16:
// anything
break;
}
}
And to better match with your question, you should order the array first and get out the foreach after a match:
long[] results = new long[] { 15, 14, 16 };
Array.Sort(results);
foreach (long v in results)
{
switch (v)
{
case 14:
// anything
break;
case 15:
// anything
break;
case 16:
// anything
break;
default:
continue; // continue the foreach loop
}
break; // break the foreach loop because we had a valid match
}
switch (C# Reference):
Each case label specifies a constant value.
In your expected sample code, results.Contains(14) is not a constant value, so the syntax will not be valid.
I would not actually recommend to do it this way, but if you're really into switch statements...
long? CheckSpecialNumbers(long[] res)
{
var specialNumbers = new List<long>() {14, 15, 16};
var inters= specialNumbers.Intersect(res);
return inters.Count() > 0 ? (long?)inters.First() : null;
}
then you could do:
long? res = CheckSpecialNumbers(results);
switch (res)
{
case 14:
Console.WriteLine(14);
break;
case 15:
Console.WriteLine(15);
break;
case 16:
Console.WriteLine(16);
break;
}
I want write this code with switch case
A switch-case statement is used to branch the execution path according to the value of a given variable. The OP wants to branch according to the value of a Boolean expression, specifically, the return value of Contains. This can only be done using an if-else statement. Writing switch (results) doesn't make sense, since results is an array of integers.