- Home /
C# switch: A constant value is expected
Hi everyone,
I have a large switch statement in my question and answer program that has "error CS0150: A constant value is expected." I researched this type of problem and it pertains mostly to typeOf switches, but my cases seem different. Here is an example of one of my cases:
case C_Jarvis.C_myString.ToLower().Contains("good") && C_Jarvis.C_myString.ToLower().Contains("how") && C_Jarvis.C_myString.ToLower().Contains("you?"):
Q1I1=true;
Debug.Log("Q1I1 true");
break;
Also, the JavaScript counterpart that I developed earlier as a prototype worked perfectly, and without errors; exactly how I wanted it to work.
Please help me understand why this error is appearing and possibly how to fix it. In more detail, this is a database that defines its questions and answers. Unless I absolutely have to, I do not want to use if statements, as this database will in the future contain hundreds of such cases and I do not want to clutter the script with hundreds of ifs.
I appreciate your help!
-Hyperion
Also, according to http://msdn.microsoft.com/en-us/library/6weteh5e%28v=vs.90%29.aspx the case must be a non-variable case in order to prevent the problem. So variable cases in JavaScript are viable but not in C#?
For hundreds of these, worth it to learn the good way:
Write a small class which holds lists of words. For the example above, just ["good", "how", "you"]
. There might also be a var for a "mustStartWith" word, or "must not have" words ... . Put all 100 cases in a list of these. Then have a loop scan the list vs. your phrase.
Even if you do go with ifs, run ConvertToLower only 1 time! w=myString.ToLower(); if(w.Contains...
@Owen_Reynolds As an initial step, I did void Start(){ string s = C_Jarvis.C_myString.ToLower(); }
and then did s.Contains(...)etc... But now the program is not doing anything. Is the problem in the variable type?
The idea is, each time you get a new C_Jarvis, could create a lower-case version. So can't do it in Start, since it only happens once, and C_Jarvis doesn't even have a value.
But, it seems you don't have a lot of program$$anonymous$$g experience. The worst thing you can do is take a bunch of fancy advice from different people (including me.) Stick to things that work for you, and the fancy stuff will come later.
Answer by SirCrazyNugget · Jun 05, 2014 at 03:49 AM
Unfortunately, that's not possible in C# due to the way it pre-compiles the code and requires constants, it can do multiple cases or numerical calculations but those won't help you.
Why not throw all possibilities into a list or multidimensional array and run through each possibility, it could start effecting performance with so many string operations so use some sort methods like most possible answer or just alphabetical sorts and give it a hand in where to start searching.
If you want to avoid using so many if and if else use a while and use a function which handles the comparisons for you. Depending on the number of possibilities you'll want to either favour using a predetermined list (higher on memory) or on-the-fly searches (higher on CPU).
void Start(){
string C_Jarvis_etc = "Good how are you?";
CaseContains(C_Jarvis_etc, new string[]{"bad", "times"});
CaseContains(C_Jarvis_etc, new string[]{"good", "how", "you"});
}
bool CaseContains(string str, string[] inStrs){
string lowerStr = str.ToLower();
foreach (string s in inStrs){
if(!lowerStr.Contains (s)){
Debug.Log (str + " didn't contain: " + s);
return false;
}
}
Debug.Log (str + " contained everything!");
return true;
}
If you plan on using the list then go for something like:
void Start(){
lstCmps = new List<string[]>();
lstCmps.Add (new string[]{"bad", "times"});
lstCmps.Add (new string[]{"good", "how", "you?"});
lstCmps.Add (new string[]{"stopped", "looking"});
Debug.Log (C_Jarvis_Contains ("Good how are you?"));
Debug.Log (C_Jarvis_Contains ("Have you stopped looking"));
Debug.Log (C_Jarvis_Contains ("You won't find this"));
}
int C_Jarvis_Contains(string str){
for(int i = 0; i < lstCmps.Count; i++){
if(CaseContains (str, lstCmps[i])){
return i;
}
}
return -1;
}
bool CaseContains(string str, string[] inStrs){
string lowerStr = str.ToLower();
foreach (string s in inStrs){
if(!lowerStr.Contains (s)){
return false;
}
}
return true;
}
The latter way you can perform a switch on the integer returned if you really need to use a switch statement.
Thank you! Would you know a link where I can find most of the string operations in your code, so that I can understand it better? (I am not too experienced in calling information from strings and creating info from them...)
$$anonymous$$ost are custom functions but I'll go through most variables/functions with a little bit more insight First example
//entry point for the script
void Start(){
//variable for the users input
string C_Jarvis_etc = "Good how are you?";
//two tests which will require if comparisons
CaseContains(C_Jarvis_etc, new string[]{"bad", "times"});
CaseContains(C_Jarvis_etc, new string[]{"good", "how", "you"});
//third test which acts on result
if(CaseContains(C_Jarvis_etc, new string[]{"Good", "you?"})){
Debug.Log ("Did contain 'Good' 'you'");
//do something extra
}
}
//function to evaluate if all inStrs appear in str
//returns true or false
bool CaseContains(string str, string[] inStrs){
//converts and temporarily stores string str to lowercase
//try to $$anonymous$$imise the number of times you perform any string operation
string lowerStr = str.ToLower();
//iterates through each of the strings in the inStrs array
//and returns false if it isn't contained
foreach (string s in inStrs){
//if !lowerStr.Contains(s) is the same as
//if lowerStr.Contains(s) == false
//as all words must be found when one doesn't exist function exits
if(!lowerStr.Contains (s)){
Debug.Log (str + " didn't contain: " + s);
return false;
}
}
//as all strings have been found return true
Debug.Log (str + " contained everything!");
return true;
}
Second example List lstCmps;
//entry point for the script
void Start(){
//create a list for all possible comparisons
lstCmps = new List<string[]>();
//populate the list
lstCmps.Add (new string[]{"bad", "times"});
lstCmps.Add (new string[]{"good", "how", "you?"});
lstCmps.Add (new string[]{"stopped", "looking"});
//three test user inputs to analyse
Debug.Log (C_Jarvis_Contains ("Good how are you?"));
Debug.Log (C_Jarvis_Contains ("Have you stopped looking"));
Debug.Log (C_Jarvis_Contains ("You won't find this"));
}
//returns an integer of the index which contained the string str
int C_Jarvis_Contains(string str){
//iterates through predefined list of options
//returns index when all required strings are found
for(int i = 0; i < lstCmps.Count; i++){
if(CaseContains (str, lstCmps[i])){
return i;
}
}
//returns -1 when string isn't found
return -1;
}
//function to evaluate if all inStrs appear in str
//returns true or false
bool CaseContains(string str, string[] inStrs){
//converts and temporarily stores string str to lowercase
string lowerStr = str.ToLower();
//iterates through each of the strings in the inStrs array
//and returns false if it isn't contained
foreach (string s in inStrs){
//if !lowerStr.Contains(s) is the same as
//if lowerStr.Contains(s) == false
if(!lowerStr.Contains (s)){
return false;
}
}
//as all strings have been found return true
return true;
}
Answer by rutter · Jun 05, 2014 at 02:56 AM
If you want to use a switch
in C#, your cases must be constant expressions that can be fully resolved at compile time.
New programmers tend to assume that switches are internally implemented by a series of if-then-else
branches. That's not as true as you might guess. In C#, they're implemented by highly optimized jump tables that are fully resolved ahead of time by the compiler; if the compiler doesn't know your case values, it can't do any of that.
If you really do need to use a variable expression, just use if
statements.
So, sorry, but there's no way to do that. Not how the language or the feature were designed. The good news is that easy workarounds are available.
Alright, thanks. That's what I assumed but I was hoping that there was a more comfortable solution.
Answer by frankiboss · Jul 10, 2014 at 10:55 AM
This works, only need to cast the variable and put the enum in order.
public enum Estados{ BLIND, DEAD }
//BLIND = 0 and DEAD = 1 and keep going
switch ((int)estado){
case 0:
Debug.Log ("Estado: " + estado);
break;
case 1:
Debug.Log ("Estado: " + estado);
break;
case 2:
Debug.Log ("Estado: " + estado);
break;
case 3:
Debug.Log ("Estado: " + estado);
break;
case 4:
Debug.Log ("Estado: " + estado);
break;
}
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
What is wrong with my c# switch statement? 1 Answer
Variable value not changing (bug or i'm just an idiot?) 0 Answers
Save Values On Closing of Game 1 Answer