可能重复:
C# - Is there a better alternative than this to ‘switch on type’?
如果你想对某种类型的对象switch
,最好的方法是什么?
private int GetNodeType(NodeDTO node)
{
switch (node.GetType())
{
case typeof(CasusNodeDTO):
return 1;
case typeof(BucketNodeDTO):
return 3;
case typeof(BranchNodeDTO):
return 0;
case typeof(LeafNodeDTO):
return 2;
default:
return -1;
}
}
我知道这不起作用,但我想知道如何解决这个问题。
在这种情况下,if/else
声明是否合适?
或者您是否使用此开关并将.ToString()
添加到类型?
答案 0 :(得分:101)
这不会直接解决您的问题,因为您想要打开自己的用户定义类型,但为了其他只想打开内置类型的人的利益,您可以使用TypeCode枚举:
switch (Type.GetTypeCode(node.GetType()))
{
case TypeCode.Decimal:
// Handle Decimal
break;
case TypeCode.Int32:
// Handle Int32
break;
...
}
答案 1 :(得分:71)
如果我真的必须switch
对象类型,我会使用.ToString()
。但是,我会不惜一切代价避免它:IDictionary<Type, int>
会做得更好,visitor可能是一种矫枉过正,但除此之外它仍然是一个非常好的解决方案。
答案 2 :(得分:40)
在MSDN博文中, Many Questions: switch on type 是关于.NET未提供切换类型的原因的一些信息。
像往常一样 - 解决方法始终存在。
这个不是我的,但不幸的是我失去了源头。它使得切换类型成为可能,但我个人认为这很尴尬(字典的想法更好):
public class Switch
{
public Switch(Object o)
{
Object = o;
}
public Object Object { get; private set; }
}
/// <summary>
/// Extensions, because otherwise casing fails on Switch==null
/// </summary>
public static class SwitchExtensions
{
public static Switch Case<T>(this Switch s, Action<T> a)
where T : class
{
return Case(s, o => true, a, false);
}
public static Switch Case<T>(this Switch s, Action<T> a,
bool fallThrough) where T : class
{
return Case(s, o => true, a, fallThrough);
}
public static Switch Case<T>(this Switch s,
Func<T, bool> c, Action<T> a) where T : class
{
return Case(s, c, a, false);
}
public static Switch Case<T>(this Switch s,
Func<T, bool> c, Action<T> a, bool fallThrough) where T : class
{
if (s == null)
{
return null;
}
T t = s.Object as T;
if (t != null)
{
if (c(t))
{
a(t);
return fallThrough ? s : null;
}
}
return s;
}
}
用法:
new Switch(foo)
.Case<Fizz>
(action => { doingSomething = FirstMethodCall(); })
.Case<Buzz>
(action => { return false; })
答案 3 :(得分:24)
我只是使用if语句。在这种情况下:
Type nodeType = node.GetType();
if (nodeType == typeof(CasusNodeDTO))
{
}
else ...
另一种方法是:
if (node is CasusNodeDTO)
{
}
else ...
第一个例子仅适用于确切类型,后者也检查继承。
答案 4 :(得分:23)
我遇到了同样的问题并且发现了这篇文章。 这是IDictionary方法的意思:
Dictionary<Type, int> typeDict = new Dictionary<Type, int>
{
{typeof(int),0},
{typeof(string),1},
{typeof(MyClass),2}
};
void Foo(object o)
{
switch (typeDict[o.GetType()])
{
case 0:
Print("I'm a number.");
break;
case 1:
Print("I'm a text.");
break;
case 2:
Print("I'm classy.");
break;
default:
break;
}
}
如果是这样,我不能说我喜欢将字典中的数字与案例陈述进行协调。
这将是理想的,但字典引用会杀死它:
void FantasyFoo(object o)
{
switch (typeDict[o.GetType()])
{
case typeDict[typeof(int)]:
Print("I'm a number.");
break;
case typeDict[typeof(string)]:
Print("I'm a text.");
break;
case typeDict[typeof(MyClass)]:
Print("I'm classy.");
break;
default:
break;
}
}
我还忽略了另一种实现吗?
答案 5 :(得分:12)
你可以这样做:
if (node is CasusNodeDTO)
{
...
}
else if (node is BucketNodeDTO)
{
...
}
...
虽然那会更优雅,但它可能没有其他一些答案那么高效。
答案 6 :(得分:9)
你可以这样做:
function void PrintType(Type t) {
var t = true;
new Dictionary<Type, Action>{
{typeof(bool), () => Console.WriteLine("bool")},
{typeof(int), () => Console.WriteLine("int")}
}[t.GetType()]();
}
很清楚也很容易。 它比在某处缓存字典要慢一些..但是对于很多代码来说这无关紧要..
答案 7 :(得分:7)
一种方法是向NodeDTO添加一个纯虚拟GetNodeType()方法,并在后代中覆盖它,以便每个后代返回实际类型。
答案 8 :(得分:4)
根据您在switch语句中的操作,正确答案是多态。只需在接口/基类中放置一个虚函数,并覆盖每个节点类型。
答案 9 :(得分:0)
我在交换机顶部使用字符串(Name):
private int GetNodeType(NodeDTO node)
{
switch (node.GetType().Name)
{
case "CasusNodeDTO":
return 1;
break;
case "BucketNodeDTO":
return 3;
break;
// ...
default:
return -1;
break;
}
}
答案 10 :(得分:0)
我实际上更喜欢这里给出的方法: Is there a better alternative than this to 'switch on type'?
然而,有一个很好的论据是没有在像C#这样的面向对象语言中实现任何类型比较方法。您可以使用继承作为替代扩展并添加额外的必需功能。
这一点在作者博客的评论中进行了讨论: http://blogs.msdn.com/b/jaredpar/archive/2008/05/16/switching-on-types.aspx#8553535
我发现这是一个非常有趣的观点,它改变了我在类似情况下的做法,只希望这有助于其他人。
亲切的问候,韦恩