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;
}
}
This question is related to
c#
.net
optimization
switch-statement
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); }
}
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.
Yes, you can switch on the name...
switch (obj.GetType().Name)
{
case "TextBox":...
}
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);
Source: Stackoverflow.com