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.
Related
I know that case cannot work with non-constant values, but what should I do if its impossible to make a constant? thats my case: we have three variables, need to find that, one that will correspond to the value of the switch condition, but how to do this if the case is not able to work with non-constants? are there any workarounds?
float value = 4;
float number1 = 3, number2 = 6, number3 = 4;
switch (value)
{
case number1:
{
break;
}
case number2:
{
break;
}
case number3:
{
break;
}
}
here is the oversimplified example, and yes, you can easily do this using if/else if, but what if the number of values will be 100? what to do in that case?
One approach is to use an inverted Dictionary, where the key is the value and the value the key. Something like this:
var d = new Dictionary<int, int>();
d.Add(3, 1);
d.Add(6, 2);
d.Add(4, 3);
int keyPtr = d[value];
switch (keyPtr):
{
case 1:
//do something.
break;
case 2:
//do something else.
break;
case 3:
//do something different.
break;
}
Obviously this is simplified, and I have used int not float, but the same applies to any type. Using this technique,
your n variables, become the first n items in the Dictionary. In practice at the very least, you should check if your given value exists as a key in the Dictionary. It should help you in the right direction.
If you simply want to check whether your value variable equals to at least one of the variables number1, number2, number3, you could create an array of those numbers, say numbers[] and then create a method such as:
private bool checkValue(float value, float[] numbers) {
foreach (float num in numbers) {
if (num == value) return true;
}
return false;
}
This solution fits any number of elements in your numbers array.
If you want you can also use a List<float> instead of an array, so you could dynamically add more and more elements (Without a fixed size).
struct person
{
public int id;
public long phone;
public string name, family, add;
public void Show()
{
Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}", id, name, family, phone, add);
}
}
class Program
{
static List<person> info = new List<person>();
static void Edit()
{
Display();
Console.Write("Choose your target ID:");
int ed = Convert.ToInt32(Console.ReadLine());
for (int i = 0; i < info.Count; i++)
{
if (ed == info[i].id)
{
Console.WriteLine("1.ID\n2.Name\n3.FamilyName\n4.PhoneNumber\n5.Address\n6.Exit to menu");
Console.WriteLine("Which part of the user info would you like to update:");
int ed1 = Convert.ToInt32(Console.ReadLine());
bool exm = false;
while (true)
{
switch (ed1)
{
case 1:
break;
case 2:
Console.Write("Enter Your Name:");
info[i].name = Console.ReadLine();
break;
case 3:
Console.Write("Enter Your FamilyName:");
info[i].family = Console.ReadLine();
break;
case 4:
Console.Write("Enter Your Name:");
info[i].phone = Convert.ToInt64(Console.ReadLine());
break;
case 5:
Console.Write("Enter Your Name:");
info[i].add =Console.ReadLine();
break;
case 6:
if (exm == true)
Main();
break;
default:
Console.WriteLine("Invalid Operation");
break;
}
}
}
}
}
I'm trying to make a program that gets users info then shows them what they can do. The program methods include input, display, search, remove, edit, all work fine but edit. I don't know how to make it work.
For edit I'm gonna get user id, then let him choose which part of that id he wants to change. In all cases I tried to replace new info but it shows me an error on info[i].would you help me to do this in this way?
You cannot change a property of a struct stored in a list; either change your struct to a class and you will then be able to modify individual properties, or change your editing routine so that it either
creates a whole new Person struct using all the data from the existing person struct with the new bit of data you want to change, and replace the old person struct in the list with the new one you've made or
gets the person out of the list into a temporary variable, changes the name, puts the temp variable back into the list
As an academic exercise I suppose it's teaching you about value types but it's a bit abstruse; perhaps your teacher is hoping you will pick up on the fact that accessing list[x] creates a copy of what is in the list at x. As there is no point editing a copy (and then throwing the copy away, as a direct edit would do) the compiler warns you that it's not possible.
You are getting the error because structs are value type.
When you do info[i] it returns value of the element at i rather than the reference to it. Modifying this value by calling setter doesn't change anything in the actual struct instance. Hence the error.
A naive workaround would be
info[i]=new person{name= Console.ReadLine()};
If not for an assignment, you should definetely use classes in these cases
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
I'm just posting mostly to see if there is a better way to do this. My biggest pet peeve in C# is definitely the excessive overuse of If statements to determine what function should be executed ie:
if (comboBoxEdit1.Text == "Soup")
else if (comboBoxEdit1.Text == "Salad")
//Continues on for 10 more statements
So what I am wondering is if it is possible for me to determine how I should parse a certain value inside of a textbox, based on what is selected index of my combobox is.
ie: comboBox is Int32
Int32.TryParse(textEdit1.Text, out i);
Is the best way really to use the if statements? Any help would be appreciated!
Edit: Full Code
//Convert.To(x) depends on combo box
searchVal = BitConverter.GetBytes(Convert.ToUInt32(searchBox.Text));
toGet = (uint)searchVal.Length;
for (uint i = 0; i <= memSize/toGet; i++)
{
uint address = startAddress + (i * toGet);
byte[] recoveredMem = XboxSupport.GetMem(address, toGet);
if (recoveredMem == searchVal)
{
if (valType == "UInt32")
{
uint val = BitConverter.ToUInt32(recoveredMem, 0);
siInfo.Caption = String.Format("{0} Found At Address: {1}", val, String.Format("0x" + String.Format("{0:X}", address)));
File.AppendAllText(path, String.Format("0x" + String.Format("{0:X}", address) + " | {0}", "{1}", val, Environment.NewLine));
}
}
Basic Summary of Code:
Recovers memory from a specific block, determined by the user, and searches that area for a value they would like to find during run time, then compiles a list of the search results inside a text file.
Perhaps a switch - case might help. Instead of using all the 'if' statements, you can use the switch statement. Here's an example:
switch(comboBox1.Text)
{
case "Soup":
//Function
break;
case "Salad":
case "AnotherItem":
//Do Something
break;
case "AnotherAnotherItem":
//Do Something else
break;
default:
//Not specified.
break;
}
Would that help? In each case you can choose do a specific function, etc.
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.