使用Case / Switch和GetType来确定对象

可能重复:
C# – 有没有比这更好的替代“打开types”?

如果你想switch一个types的对象,最好的办法是什么?

代码片段

 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()的types?

如果我真的不得不switchtypes的对象,我会使用.ToString() 。 但是,我会不惜一切代价避免它: IDictionary<Type, int>会做得更好, 访问者可能是一个矫枉过正,但否则它仍然是一个完美的解决scheme。

这不会直接解决您的问题,因为您希望切换自己的用户定义types,但是为了其他只想切换内置types的用户,您可以使用TypeCode枚举:

 switch (Type.GetTypeCode(node.GetType())) { case TypeCode.Decimal: // Handle Decimal break; case TypeCode.Int32: // Handle Int32 break; ... } 

在MSDN博客文章中有许多问题:开启types是为什么.NET不提供types切换的一些信息。

像往常一样,变通办法始终存在。

这一个不是我的,但不幸的是我已经失去了源。 它使得可能的切换types,但我个人认为这是相当尴尬(字典的想法是更好的):

  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; }) 

我只是使用一个if语句。 在这种情况下:

 Type nodeType = node.GetType(); if (nodeType == typeof(CasusNodeDTO)) { } else ... 

另一种方法是:

 if (node is CasusNodeDTO) { } else ... 

第一个例子只适用于确切的types,后者也检查inheritance。

我面临着同样的问题,并遇到这个职位。 这是什么意思的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; } } 

我忽略了另一个实现吗?

你可以这样做:

 if (node is CasusNodeDTO) { ... } else if (node is BucketNodeDTO) { ... } ... 

虽然这可能会更优雅,但可能并不像其他答案那样高效。

一种方法是向NodeDTO添加一个纯虚拟GetNodeType()方法,并在后代中重写它,以便每个后代返回实际types。

你可以这样做:

 function void PrintType(Type t) { var t = true; new Dictionary<Type, Action>{ {typeof(bool), () => Console.WriteLine("bool")}, {typeof(int), () => Console.WriteLine("int")} }[t.GetType()](); } 

这很清楚,很容易。 这比caching字典的地方慢一点..但是对于大量的代码,这无关紧要..

根据你在switch语句中做什么,正确的答案是多态。 只需在接口/基类中放置一个虚拟函数,并覆盖每个节点types。

我会使用交换机顶部的string(Name):

  private int GetNodeType(NodeDTO node) { switch (node.GetType().Name) { case "CasusNodeDTO": return 1; break; case "BucketNodeDTO": return 3; break; // ... default: return -1; break; } } 

我其实更喜欢这里给出的方法: 有没有比这更好的替代方法来“打开types”?

然而有一个很好的论点,就是没有在像C#这样的面向对象的语言中实现任何types的比较方法。 您可以select使用inheritance扩展并添加额外的必需function。

这一点在作者博客的评论里讨论过: http : //blogs.msdn.com/b/jaredpar/archive/2008/05/16/switching-on-types.aspx#8553535

我发现这是一个非常有趣的观点,改变了我在类似情况下的做法,只希望这有助于其他人。

亲切的问候,韦恩