可能重复:
C# - Is there a better alternative than this to 'switch on type'?
你好假设我在类类型上获得了一个很大的if / else。有没有办法用开关盒做到这一点?
示例:
function test(object obj)
{
if(obj is WebControl)
{
}else if(obj is TextBox)
{
}
else if(obj is ComboBox)
{
}
等等......
我想创建像
这样的东西switch(obj)
{
case is TextBox:
break;
case is ComboBox:
break;
}
}
答案 0 :(得分:59)
没有。
http://blogs.msdn.com/b/peterhal/archive/2005/07/05/435760.aspx
我们收到很多关于C#语言和今天的添加请求 我将谈谈一个比较常见的 - 开启类型。 开启类型看起来像一个非常有用和直接的功能: 添加一个类似开关的结构,它可以打开类型 表达式,而不是值。这可能看起来像 这样:
switch typeof(e) {
case int: ... break;
case string: ... break;
case double: ... break;
default: ... break;
}
这种声明对于添加虚拟非常有用 方法,如在不相交的类型层次结构上调度,或在类型上调度 包含您不拥有的类型的层次结构。看到像这样的例子 这个,你可以很容易地得出这个特征的结论 简单而有用。它甚至可能让你想到“为什么不 那些#*&%$懒惰的C#语言设计师让我的生活更轻松 添加这个简单,省时的语言功能?“
不幸的是,像许多'简单'的语言功能一样,类型切换是 并不像它第一次出现那么简单。当你看时,麻烦就开始了 一个更重要,同样重要的例子:
class C {}
interface I {}
class D : C, I {}
switch typeof(e) {
case C: … break;
case I: … break;
default: … break;
}
链接:https://blogs.msdn.microsoft.com/peterhal/2005/07/05/many-questions-switch-on-type/
是: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));
}
答案 1 :(得分:50)
以下代码或多或少地起作用,因为人们期望只查看实际类型的类型开关(例如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");
}
这是使其工作所需的机器。
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); }
}
答案 2 :(得分:22)
是的,你可以打开名字......
switch (obj.GetType().Name)
{
case "TextBox":...
}
答案 3 :(得分:13)
这是一个保持真实的选项我可以满足OP要求能够打开类型。如果你足够眯眼,它几乎看起来像一个真正的开关声明。
调用代码如下所示:
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);
上面每个lambda中的x
是强类型的。无需铸造。
为了完成这项神奇的工作,你需要这两种方法:
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;
}
几乎给你的眼睛带来了眼泪,对吗?
尽管如此,它仍然有效。享受。
答案 4 :(得分:9)
最简单的方法是使用动力学,即你在Yuval Peled回答中定义简单的方法:
void Test(WebControl c)
{
...
}
void Test(ComboBox c)
{
...
}
然后你不能直接调用Test(obj),因为重载解析是在编译时完成的。您必须将对象分配给动态,然后调用Test方法:
dynamic dynObj = obj;
Test(dynObj);