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.