Introduction
We all know what a switch
case is, henceforth there is no need for further explanation of that.
But the current one present in C# does lack certain features (at least according to me) and I am going to list them down.
Case 1: Multiple case statement problem
Consider the below:
int i = 1;
switch (i)
{
case 0: MessageBox.Show("Hello, this is 0"); break;
case 1:
case 2: MessageBox.Show("Hello, this is 1 and 2 block"); break;
}
As we find that, Case 1 and 2 share the same piece of code but we need to declare two
case
statements for doing so. Just consider, if the
case
exceeds a large number….
Would not it have been handy if we have:
int i = 1;
switch (i)
{
case 0: MessageBox.Show("Hello, this is 0"); break;
case 1..2: MessageBox.Show("Hello, this is 1 and 2 block"); break;
}
We just have to specify the start and the end values within the ellipses(..) and the job is done.
Case 2: Accepts only certain data types
A switch expression or case label accepts only the below data types:
- Bool
- Char
- String
- Integral
- Enum
- Nullable data types
Henceforth, the following will not even compile:
double i = 1.0;
switch (i)
{
}
Case 3: Does not support mixed data type
Consider the following which will happily fail:
int i = 1;
switch (i)
{
case 0: MessageBox.Show("Hello, this is 0"); break;
case "A":
case "B": MessageBox.Show("Hello, this is block A and B"); break;
}
By giving the error message Cannot implicitly convert type string to int
Won’t it be nice if we have those features incorporated into the switch
statement? Let us see how we can do so.
Background
I was going through an answer in Stack Overflow when I hit upon this idea of making a custom switch
case. I have just tried to play around with the idea in .NET and it has been implemented here. Let’s see how it goes.
Straight to code
Let us have a class:
public class SwitchClass<T> : Dictionary<string, Func<T>>
{
public T Execute(string key)
{
if (this.ContainsKey(key)) return this[key]();
else return default(T);
}
}
This is a generic class that inherits a
dictionary
object. We have a method call
Execute
which is again generic and it accepts a key. If a match is found, it returns the value else let us see this new stuff in action.
Case 1: Solving Multiple Case statement
Let us invoke it as under:
int result = 0;
new SwitchClass<int>
{
{ "case 1", ()=> result = 1 },
{ "case 2..10", ()=>result = 20 },
}.Execute("case 2..10");
MessageBox.Show(result.ToString());
The output being 20 in this case. We are specifying the
case
statements in the key list and the values will the returned in the
Func
delegate. The class is typed which is integer in this case and henceforth the return value will always be of type
integer
.
Case 2: Solving limited data types acceptance problem
double result = 0;
new SwitchClass<double>
{
{ "case 1", ()=>result += 1.0 },
{ "case 2..10", ()=>result += 20.12 },
}.Execute("case 1");
MessageBox.Show(result.ToString());
The value is 10 as expected. As we can see that our
switch
case accepts
double
here. It can accept any kind of object.
Limitation of this approach
Since it is type safe, we cannot accommodate the third limitation of the general
switch
statement here. But it can be done by a little bit of modification.
Let us modify our
SwitchClass
as under:
public class ModifiedSwitchCase : Dictionary<string, Func<object>>
{
public void Execute(string key)
{
if (this.ContainsKey(key)) this[key]();
}
}
The change is that we have removed the generic type and the
Func
delegate will return an object.
Case 3: Solving the mixed data type support
var result = 0;
new ModifiedSwitchCase
{
{ "case 0", ()=> result = 10 },
{ "case A..B", ()=> MessageBox.Show("Hello, this is block A and B") },
}.Execute("case 0");
MessageBox.Show(result.ToString());
The value will be
10
here.
Conclusion
Hope this little tip will be helpful. Comments and suggestions are welcome.
Thanks for reading.