Switch case on type c#
C#.NetOptimizationSwitch StatementC# Problem Overview
> Possible Duplicate:
> C# - Is there a better alternative than this to 'switch on type'?
Hello suppose i get a big if/else on class type. it's there a way to do it with a switch case ?
Example :
function test(object obj)
{
if(obj is WebControl)
{
}else if(obj is TextBox)
{
}
else if(obj is ComboBox)
{
}
etc ...
I would like to create something like
switch(obj)
{
case is TextBox:
break;
case is ComboBox:
break;
}
}
C# Solutions
Solution 1 - C#
Update C# 7
Yes: Source
switch(shape)
{
case Circle c:
WriteLine($"circle with radius {c.Radius}");
break;
case Rectangle s when (s.Length == s.Height):
WriteLine($"{s.Length} x {s.Height} square");
break;
case Rectangle r:
WriteLine($"{r.Length} x {r.Height} rectangle");
break;
default:
WriteLine("<unknown shape>");
break;
case null:
throw new ArgumentNullException(nameof(shape));
}
Prior to C# 7
No.
http://blogs.msdn.com/b/peterhal/archive/2005/07/05/435760.aspx
> We get a lot of requests for addditions to the C# language and today > I'm going to talk about one of the more common ones - switch on type. > Switch on type looks like a pretty useful and straightforward feature: > Add a switch-like construct which switches on the type of the > expression, rather than the value. This might look something like > this:
switch typeof(e) {
case int: ... break;
case string: ... break;
case double: ... break;
default: ... break;
}
> This kind of statement would be extremely useful for adding virtual > method like dispatch over a disjoint type hierarchy, or over a type > hierarchy containing types that you don't own. Seeing an example like > this, you could easily conclude that the feature would be > straightforward and useful. It might even get you thinking "Why don't > those #*&%$ lazy C# language designers just make my life easier and > add this simple, timesaving language feature?" > > Unfortunately, like many 'simple' language features, type switch is > not as simple as it first appears. The troubles start when you look at > a more significant, and no less important, example like this:
class C {}
interface I {}
class D : C, I {}
switch typeof(e) {
case C: … break;
case I: … break;
default: … break;
}
Link: https://blogs.msdn.microsoft.com/peterhal/2005/07/05/many-questions-switch-on-type/
Solution 2 - C#
The following code works more or less as one would expect a type-switch that only looks at the actual type (e.g. what is returned by GetType()
).
public static void TestTypeSwitch()
{
var ts = new TypeSwitch()
.Case((int x) => Console.WriteLine("int"))
.Case((bool x) => Console.WriteLine("bool"))
.Case((string x) => Console.WriteLine("string"));
ts.Switch(42);
ts.Switch(false);
ts.Switch("hello");
}
Here is the machinery required to make it work.
public class TypeSwitch
{
Dictionary<Type, Action<object>> matches = new Dictionary<Type, Action<object>>();
public TypeSwitch Case<T>(Action<T> action) { matches.Add(typeof(T), (x) => action((T)x)); return this; }
public void Switch(object x) { matches[x.GetType()](x); }
}
Solution 3 - C#
Yes, you can switch on the name...
switch (obj.GetType().Name)
{
case "TextBox":...
}
Solution 4 - C#
Here's an option that stays as true I could make it to the OP's requirement to be able to switch on type. If you squint hard enough it almost looks like a real switch statement.
The calling code looks like this:
var @switch = this.Switch(new []
{
this.Case<WebControl>(x => { /* WebControl code here */ }),
this.Case<TextBox>(x => { /* TextBox code here */ }),
this.Case<ComboBox>(x => { /* ComboBox code here */ }),
});
@switch(obj);
The x
in each lambda above is strongly-typed. No casting required.
And to make this magic work you need these two methods:
private Action<object> Switch(params Func<object, Action>[] tests)
{
return o =>
{
var @case = tests
.Select(f => f(o))
.FirstOrDefault(a => a != null);
if (@case != null)
{
@case();
}
};
}
private Func<object, Action> Case<T>(Action<T> action)
{
return o => o is T ? (Action)(() => action((T)o)) : (Action)null;
}
Almost brings tears to your eyes, right?
Nonetheless, it works. Enjoy.
Solution 5 - C#
The simplest thing to do could be to use dynamics, i.e. you define the simple methods like in Yuval Peled answer:
void Test(WebControl c)
{
...
}
void Test(ComboBox c)
{
...
}
Then you cannot call directly Test(obj), because overload resolution is done at compile time. You have to assign your object to a dynamic and then call the Test method:
dynamic dynObj = obj;
Test(dynObj);