How can I make loop instead of switch statement? - c#

How can I write this shorter? For each case I have to write this and then It is too long because there are 48 numbers so I need 48 cases. Is there a way to make a loop?
switch (ballBounce.ToString())
{
case "1":
if (ballBounce == n0)
{
textBox1.Text = number.ToString();
}
break;
case "2":
if (ballBounce == n1)
{
textBox1.Text = number.ToString();
}
break;
case "3":
if (ballBounce == n2)
{
textBox1.Text = number.ToString();
}
break; ...

The loop is useless in this case.
You can use dictionary.
private Dictinoary<string, string> cases = new Dictionary<string, string> {
{"1", "one"},
{"2", "two"},
// ...
};
// in some method
string text;
if (cases.TryGetValue(ballBounce.ToString(), out text)){
this.textBox1.Text = text;
}
If you want something smarter than simple value, you can have functions in the dictionary.
private Dictinoary<string, Func<string>> cases = new Dictionary<string, Func<string>> {
{"1", () => "one"},
{"2", () =>
{
if (DateTime.Now.Seconds % 2 == 0) { return "A"; }
else { return "B"; }
}},
// ...
};
// in some method
Func<string> textProvider;
if (cases.TryGetValue(ballBounce.ToString(), out textProvider)){
this.textBox1.Text = textProvider();
}

Based on your ToString()'s, I'm assuming that ballBounce is an int.
if (ballBounce <= 48 && ballBounce > 0)
{
textBox1.Text = ballBounce.ToString();
}

why do you use if with case?
you don't need to check twice.
also if this is the code for every case
textBox1.Text = number.ToString();
then you don't need switch or if
jsut write textBox1.Text = number.ToString(); and you are good to go.
also if you have some cases ony you can do it that way:
switch (ballBounce.ToString())
{
case "1":
case "2":
case"3":
//....
textBox1.Text = number.ToString();
}

Related

Get column index as constant value

Currently i am having code like this inside dataGridView1_CellValidating event:
if(e.ColumnIndex == dataGridView1.Columns["FIRST"].Index)
{
// Some code
}
else if(e.ColumnIndex == dataGridView1.Columns["Second"].Index)
{
// Some code
}
else if(e.ColumnIndex == dataGridView1.Columns["Third"].Index)
{
// Some code
}
And it is like this because i cannot use it in switch statement like:
switch(e.ColumnIndex)
{
case dataGridView.Columns["First"].Index:
break;
case dataGridView.Columns["Second"].Index:
break;
case dataGridView.Columns["Third"].Index:
break;
}
returns me error on case line Expecting constant value.
So how can i make this work?
The switch statement is complaining because the “case” portion of the statement “requires” a “CONSTANT” value. The statement dataGridView.Columns["First"].Index will always return the same value… unless you move the column… which you can do. This is why the compiler is going to look at the retuned value from dataGridView.Columns["First"].Index as NOT a “constant”.
This makes sense in the fact that the “column index” for the column named “First” could be at ANY column index in the grid… Hence the error.
A possible solution is to grab the current columns “Name” string value then switch off the column “Name” like below.
string columnName = dataGridView.Columns[e.ColumnIndex].Name;
switch (columnName) {
case "First":
MessageBox.Show("Cell Validated is in 'FIRST' column");
break;
case "Second":
MessageBox.Show("Cell Validated is in 'Second' column");
break;
case "Third":
MessageBox.Show("Cell Validated is in 'Third' column");
break;
}
If you really want to use switch you can make use of pattern matching in switch case
PS: For C# 7.0 or above
switch(e.ColumnIndex)
{
case var _ when (dataGridView.Columns["First"].Index == e.ColumnIndex):
break;
case var _ when (dataGridView.Columns["Second"].Index == e.ColumnIndex):
break;
case var _ when (dataGridView.Columns["Third"].Index == e.ColumnIndex):
break;
}
Maybe, you first make constant values and assign dataGridView.Columns["First"].Index to it.
For example:
int a = {given index}
const int IndexOfFirstCol = dataGridView.Columns["First"].Index;
const int IndexOfSecCol = dataGridView.Columns["Second"].Index;
then,
switch(a)
{
case IndexOfFirstCol:
//do smth
break;
case IndexOfSecCol:
//do smth
break;
}
If you cannot use pattern matching from C# 7.0, there is also another way by using dictonaries where your keys are functions checking the conditions (cases) and the values are the actions you want to perform. For your code it would look like:
private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
var caseDictionary = new Dictionary<Func<bool>, Action>()
{
{ () => (e.ColumnIndex == dataGridView1.Columns["First"].Index), () => { MessageBox.Show("First");}},
{ () => (e.ColumnIndex == dataGridView1.Columns["Second"].Index), () => { MessageBox.Show("Second");}},
{ () => (e.ColumnIndex == dataGridView1.Columns["Third"].Index), () => { MessageBox.Show("Third");}}
};
caseDictionary.Where(caseRecord => caseRecord.Key()).Select(action => action.Value).FirstOrDefault()?.Invoke();
}
You could of course declare the Dictionary in your constructor and just call it in the CellValidating event.
I would have another approach, using a Dictionnary (from the namespace System.Collections.Generic) of methods built in such way
The key is the index of the column in the datagridview ("First", "Second" ...)
The value is a Delegate to the method to do (what replaces your // some code in each if/else if
In example :
/*
* This example is written for console application, that can be tested easily.
* The logic can be rewritten for WinForm
*/
static void TheFirstCase()
{
//This should be replaced by the differents actions you want to do
Console.WriteLine("first case");
}
static void TheSecondtCase()
{
Console.WriteLine("second case");
}
static void TheThirdCase()
{
Console.WriteLine("third case");
}
static void Main(string[] args)
{
Dictionary<string, Delegate> MyDic = new Dictionary<string, Delegate>
{
//If you need parameters in the TheFirstCase(), use new Action<TypeOfTheFirstParam, TypeOfTheSecondParam, ...>(TheFirstCase)
//If your Method needs to return something, use Func instead of Action
{ "First", new Action(TheFirstCase) },
{ "Second", new Action(TheSecondtCase) },
{ "Third", new Action(TheThirdCase) }
};
// in your question, this is e.ColumnIndex
var ValueInColIndex = 42;
// in your question, this is dataGridView.Columns
var DataGridViewDatas = new Dictionary<string, int>
{
{ "First", 0 },
{ "Second", 42 },
{ "Third", 69 }
};
foreach (var MyAction in MyDic)
{
if (DataGridViewDatas[MyAction.Key] == ValueInColIndex)
{
MyAction.Value.DynamicInvoke();
}
}
}
Outputs :
second case

Replace 4 different characters

I'm trying to take the user input, E.G. ATCG and replace the letters with TAGC. These are DNA Complementary Bases. For example, if the user was to enter ATCGGGC it would output TAGCCCG. I've managed to replace 1 character, but I'm not sure how to get the others to replace.
namespace DNA_Replication_EASY
{
class Program
{
static string input1;
public static string InputBaseWithSpaces()
{
return string.Join(" ", input1.ToCharArray());
}
public static string OpposingBases()
{
string outputBases1 = input1.Replace("A", "T");
return outputBases1;
}
static void Main(string[] args)
{
Console.WriteLine("Please type out your DNA strand bases E.g. A T C G C A T G");
input1 = Console.ReadLine();
Console.WriteLine(InputBaseWithSpaces());
Console.WriteLine(OpposingBases());
Console.ReadLine();
}
}
}
Use Regex.Replace to replace string based on a dictionary (map):
Dictionary<string, string> complementary = new Dictionary<string,string>()
{
{ "A", "T" },
{ "T", "A" },
{ "C", "G" },
{ "G", "C" }
};
string input = "ATCG";
string result = Regex.Replace(input, "[ATCG]", match => complementary[match.Value]);
this replaces any of the "ATCG" character match with corresponding value from dictionary.
string MakeOpposite(string sourceString) {
var opposites = new Dictionary<char, char> {
{ 'A', 'T' },
{ 'T', 'A' },
{ 'G', 'C' },
{ 'C', 'G' }
};
var oppositeString = new string(sourceString.Select(x => opposites[x]));
return oppositeString;
}
Convert it to a char array and replace in place
string input = "ATCG";
//TAGC
char[] inputChar = input.ToCharArray();
for(int i=0;i< inputChar.Length; i++)
{
switch(inputChar[i])
{
case 'A':
inputChar[i]='T';
break;
case 'T':
inputChar[i]='A';
break;
case 'G':
inputChar[i]='C';
break;
case 'C':
inputChar[i]='G';
break;
}
}
var output =new string(inputChar);
I would use a foreach and switch statement over your Char Array to replace each letter.
foreach (char base in strand)
{
switch (base.ToString())
{
case "g":
//replace code
break;
case "c":
//replace code
break;
}
}
You should instead write a routine to go through character by character and do the replacement (don't use the string.replace method).
private string ConvertDNA(string original)
{
StringBuilder newone = new StringBuilder();
foreach(char c in original)
{
switch(c)
{
case 'A':
newone.Append('T');
break;
case 'T':
newone.Append('A');
break;
case 'C':
newone.Append('G');
break;
case 'G':
newone.Append('C');
break;
default:
newone.Append(c);
break;
}
}
return newone.ToString();
}
Note that if your original string is certain forms of Unicode, this could do funny things. You should use stringbuilder rather than the += syntax in the other answers because its more efficient.
One way to do it is by using a Switch statement
public static string OpposingBases()
{
string outputBases1;
foreach(var s in input1)
{
switch (s)
{
case "A":
outputBases1 +="T";
break;
case "T":
outputBases1 +="A";
break;
case "C":
outputBases1 +="G";
break;
case "G":
outputBases1 +="C";
break;
case " ":
outputBases1 +=" ";
break;
default:
break;
}
}
return outputBases1;
}
Simple solution, but you can do better:
code = code.Replace("A","x").Replace("C","y").Replace("T","A").Replace("G","C").Replace("x","T").Replace("y","G");
You could do this
public static string OpposingBases()
{
var baseDictionary = new Dictionary<char, char>()
{
{'A', 'T'},
{'T', 'A'},
{'C', 'G'},
{'G', 'C'}
};
return input1.Where(baseDictionary.ContainsKey).Aggregate("", (current, c) => current + baseDictionary[c]);
}

C# need to add random response with switch statement

namespace _7._39
{
class Program
{
static void Main(string[] args)
{
string response1;
string response2;
string response3;
string response4;
Random resp = new Random();
bool correct = Question();// Create a value to call the question method
if (correct== true)// when the answer is true it return very good
{
Console.WriteLine("Very Good!");
}
else// when the answer is false it returns to try again
{
Console.WriteLine("No please try again");
}
}
public static bool Question()
{
Random rand = new Random();// we create a random number
int num = rand.Next(1, 9);// first random number between 1 and 9
int num1 = rand.Next(1, 9);// second random number between 1 and 9
int ans = num * num1;// the value of multiplication between 1 and 2
// asking what the two values are multiplied
Console.WriteLine("What is"+ num.ToString()+ "*" +num1.ToString());
// reads the users attempt
int attempt = int.Parse(Console.ReadLine());
if (attempt == ans)// when the attempt is equal to the answer
{
return true;// its returns true bool
}
else// if it is false it says no please try again
{
Console.WriteLine("No please try again");
return Question();// and creates a new question for the user
}
}
}
}
I need my correct== true and false to respond with a random response among 4 possible choices. I need to do this by doing a switch statement to issue each response. Also by using random to select which response comes up.
Very good!
Excellent!
Nice work!
Keep up the good work!
and 4 options for a false response as well
How can i implement this code into my current code?
response = resp.Next(1, 5);
switch (response)
{
case 1:
Console.WriteLine("Very Good!");
break;
case 2:
Console.WriteLine("Excellent!");
break;
case 3:
Console.WriteLine("Nice Work!");
break;
case 4:
Console.WriteLine("Keep up the good work!");
break;
default;
}
Try this:
var rnd = new Random();
Func<bool, string> getRespose = b =>
{
var choices = b
? new [] { "Very good!", "Excellent!", "Nice work!", "Keep up the good work!", }
: new [] { "Bad!", "V Bad!", "VV Bad!", "VVV Bad!", };
return choices[rnd.Next(0, choices.Length)];
};
No need for a switch statement.
Or if you want it as a switch:
var rnd = new Random();
var choices = (string[])null;
switch (correct)
{
case true:
choices = new []
{ "Very good!", "Excellent!", "Nice work!", "Keep up the good work!", };
break;
case false:
choices = new [] { "Bad!", "V Bad!", "VV Bad!", "VVV Bad!", };
break;
}
var response = choices[rnd.Next(0, choices.Length)];
Or, with a switch and a Func:
var rnd = new Random();
Func<bool, string> getRespose = b =>
{
var choices = (string[])null;
switch (b)
{
case true:
choices = new []
{ "Very good!", "Excellent!", "Nice work!", "Keep up the good work!", };
break;
case false:
choices = new []
{ "Bad!", "V Bad!", "VV Bad!", "VVV Bad!", };
break;
}
return choices[rnd.Next(0, choices.Length)];
};
var response = getRespose(correct);
Or as a "normal" function:
private Random rnd = new Random();
private string GetRespose(bool b)
{
var choices = (string[])null;
switch (b)
{
case true:
choices = new []
{ "Very good!", "Excellent!", "Nice work!", "Keep up the good work!", };
break;
case false:
choices = new []
{ "Bad!", "V Bad!", "VV Bad!", "VVV Bad!", };
break;
}
return choices[rnd.Next(0, choices.Length)];
}
Or as a "normal" function, but without the switch:
private Random rnd = new Random();
private string GetRespose(bool b)
{
var choices = b
? new [] { "Very good!", "Excellent!", "Nice work!", "Keep up the good work!", }
: new [] { "Bad!", "V Bad!", "VV Bad!", "VVV Bad!", };
return choices[rnd.Next(0, choices.Length)];
}

is there any way to simplify this double conditional clauses structure?

for example
if (x=="A)
switch (y)
{
case "1": Do1();break;
case "2": Do2();break;
case "3": Do3();break;
}
else if (x=="B")
switch (y)
{
case "1": Do4();break;
case "2": Do5();break;
case "3": Do6();break;
}
else
switch (y)
{
case "1": Do7();break;
case "2": Do8();break;
case "3": Do9();break;
}
I wish I could do the following, however it has many redundant checks.
if (x=="A" && y=="1")
Do1();
else if (x=="A" && y=="2")
Do2();
else if (x=="A" && y=="3")
Do3();
else if (x=="B" && y=="1")
Do4();
else if (x=="B" && y=="2")
Do5();
else if (x=="B" && y=="3")
Do6();
else if (x=="C" && y=="1")
Do7();
else if (x=="C" && y=="2")
Do8();
else if (x=="C" && y=="3")
Do9();
Suggestion to introduce OOPS is really great, please do not ignore that comment. For time being you can write your code like this.
var combinedText = x+y;
switch(combinedText)
{
case "A1": Do1(); break;
case "A2": Do2(); break;
case "A3": Do3(); break;
case "B1": Do4(); break;
case "B2": Do5(); break;
case "B3": Do6(); break;
case "C1": Do7(); break;
case "C2": Do8(); break;
case "C3": Do9(); break;
}
Your code currently has two responsibilities - deciding what set of methods to execute (varible x) and deciding which exact method to execute (varible y). Simplest option to make code much more clear - split this responsibilities and extract methods, that will decide which method from set of methods to call
switch (x)
{
case "A": DoA(y); break;
case "B": DoB(y); break;
default:
DoDefault(y); break;
}
Now your caller code is simple. And here is one of DoX methods:
private void DoA(string y)
{
switch (y)
{
case "1": Do1(); break;
case "2": Do2(); break;
case "3": Do3(); break;
}
}
Other option is to make .net to decide which set of methods to call, by using polymorphism. But in your simple case with only one switch(x) block, I will not recommend to do that. If your real code is more complex, then consider to extract classes which will hold set of functionality (Do1, Do2, Do3) and will decide upon that functionality execution. E.g. calling code:
IDo ido = CreateIDo(x);
ido.Do(y);
Yes, that's all. Extremely clean. Here is IDo interface creation code:
public static IDo CreateIDo(string x)
{
switch (x)
{
case "A": return new A();
case "B": return new B();
default:
return new C();
}
}
And here is class A, that encapsulates first set of methods and decisions upon executing them:
public interface IDo
{
void Do(string y);
}
public class A : IDo
{
public void Do(string y)
{
switch (y)
{
case "1": Do1(); break;
case "2": Do2(); break;
case "3": Do3(); break;
}
}
private void Do1() { }
private void Do2() { }
private void Do3() { }
}
Again, use this in case your real code is more complex.
I would use an IEnumerable collection of Tuples and an Action delegate to define your list of methods to be called, create the list as a private field or in the class initialiser, or to be flexible you can add Tuples to a public property as needed. If you need to pass in parameters use one of the overloaded versions of the Action delegate ie: Action(t1, t2) etc.
If you need a return value use the Func delegate as per the other answer.
IEnumerable<Tuple<string, string, Action>> actions = new List<Tuple<string, string, Action>>() {
Tuple.Create<string, string, Action>("A", "1", SomeMethod1),
Tuple.Create<string, string, Action>("A", "2", SomeMethod2)
};
string x = "A";
string y = "2";
var action = actions.FirstOrDefault(t => ((t.Item1 == x) && (t.Item2 == y)));
if (action != null)
action.Item3();
else
DoSomeDefaultMethod();
public void SomeMethod1() { // Whatever you want to do }
public void SomeMethod2() { // Whatever you want to do }
public void DoSomeDefaultMethod() { // Default Method }
void Main()
{
Dictionary<string, Action> d = new Dictionary<string, Action>()
{
{"A1", Do1},
{"A2", Do2},
{"A3", Do3},
{"B1", Do4},
{"B2", Do5},
{"B3", Do6},
{"1", Do7},
{"2", Do8},
{"3", Do9}
};
var x = "A";
var y = "1";
var action = x == "A" || x == "B" ? x + y : y;
if (d.ContainsKey(action))
d[action]();
}
public void Do1() {}
public void Do2() {}
public void Do3() {}
public void Do4() {}
public void Do5() {}
public void Do6() {}
public void Do7() {}
public void Do8() {}
public void Do9() {}
EDIT
I remembered about this fluent functional switch:
var sw = new Switch<string>(action)
.Case("A1", s => Do1())
.Case("A2", s => Do2());
Consider this if you don't want to change much of your current structure,(and don't want to create new types etc.)
Add them to tuples like below
var tuples = new List<Tuple<string,string,Func<>>()>(); // Func should be of your Do() type
Add your conditional data with the related funcs to the list
tuples.Add(new Tuple<string,string,Func<>>("A","1", Do1()));
...
Just call it when required using your conditionals directly
var function = tuples.Where(x => x.item1 == "A" && x.item2 == "1").Select(x => x.item3);
function.Invoke(); // to call it.
Now if you got more conditionals in future, you can just add them to the list without changing any code.
Use some thing like this . only three if would do.
if (x == "A")
{
int a = (y == "1") ? do1() : ((y == "2") ? do2() : do3());
}
}
int do1() { return 10; }
int do2() { return 10; }
int do3() { return 10; }
I guess the same kind of switch on X is performed in more than one place in your code, if so kindly refactor it and use polymorphism instead
If X is string first replace the typecode with class and use polymorphism.

I need to replace a C# switch with something more compact

I have the following code:
switch (pk.Substring(2, 2))
{
case "00":
ViewBag.Type = _reference.Get("14", model.Type).Value;
break;
case "01":
ViewBag.Type = _reference.Get("18", model.Type).Value;
break;
}
It does the job but does not look very clean to me. Is there some way I could make this code a bit smaller. I was thinking to just have the number 14 or 18 as a variable but I am not sure the best way to code if I should use if-else or some other way.
You could use a static dictionary as a map instead of a switch-statement.
static readonly Dictionary<string, string> map = new Dictionary<string, string> {
{ "00", "14" },
{ "01", "18" },
// ... more ...
};
// ... in your method ...
string str = pk.Substring(2, 2);
string val;
if (!map.TryGetValue(str, out val))
{
// Handle error, like in the "default:" case of the switch statement
}
else
{
ViewBag.Type = _reference.Get(val, model.Type).Value;
}
However, I would only do this, if there are really a lot of mappings that maybe can even be "read" from an external source like a configuration file.
Also note, that if the "key" is really a consecutive sequence of integers starting at 0, you might be able to use an array, where the "key" is simply the index into it.
static readonly string[] map = new string[] {
"14", "18", ...
};
int index = Int32.Parse(pk.Substring(2, 2)); // Error handling elided.
if (index < 0 || index > map.Length)
{
// Handle error, like in the "default:" case of the switch statement
}
else
{
ViewBag.Type = _reference.Get(map[index], model.Type).Value;
}
Otherwise rather stay with an explicit switch statement (possibly factoring out the assignment for more terse code):
string val;
switch (pk.Substring(2, 2))
{
case "00":
val = "14";
break;
case "01":
val = "18";
break;
// ... more ...
default:
// Error handling for unknown switch-value.
break;
}
ViewBag.Type = _reference.Get(val, model.Type).Value;
It seems that there is some relationship between "00"->"14" and "01"->"18". I believe this relationship results from the business logic. You should wrap the logic and make the code in your controller clear. Finally the code in the controller should look like:
public ActionResult MyAction()
{
//some code
ViewBag.Type = TypeProvider.GetType(pk, model.Type);
//return something
}
class TypeProvider
{
Dictionary<string, string> relations = ...
//a dictionary stores "00"->"14" logics
public static SomeType GetType(string pk, Type modelType)
{
return _reference.Get(relations[pk.SubString(2,2)], modelType).Value;
}
}
var data = pk.Substring(2, 2);
var choice = data == "00" ? "14" : (data=="01"?"18":"");
if (choice != string.Empty) ViewBag.Type = _reference.Get(choice, model.Type).Value;
I use mapping extensions fot that kind of code:
ViewBag.Type = pk.Substring(2, 2)
.Map("00", x => GetViewBagValue("14"))
.Map("01", x => GetViewBagValue("18"))
and in your case this method:
private ViewBagValue GetViewBagValue(string value)
{
return _reference.Get(value, model.Type).Value;
}
I use this. You could easily change it to generic or use e.g. object[] instead. Not super efficient, but very compact:
public static class Util {
public static string Switch(string value, params string[] nameValues) {
for (int x = 0; x < nameValues.Length; x += 2) {
if (nameValues[x] == value) {
return nameValues[x + 1];
}
}
return string.Empty;
}
}
Then just call that like this:
var res = Util.Switch("test2", "test1", "res1", "test2", "res2");
Best of luck!

Categories