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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/708911/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 14:15:59  来源:igfitidea点击:

Using Case/Switch and GetType to determine the object

c#.netreflectionswitch-statementcase

提问by user29964

Possible Duplicate:
C# - Is there a better alternative than this to ‘switch on type'?

可能的重复:
C# - 有比这更好的替代方法来“打开类型”吗?

If you want to switchon a type of object, what is the best way to do this?

如果你想switch在某种类型的对象上,最好的方法是什么?

Code snippet

代码片段

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

I know this doesn't work that way, but I was wondering how you could solve this. Is an if/elsestatement appropriate in this case?

我知道这行不通,但我想知道你如何解决这个问题。if/else在这种情况下,声明是否合适?

Or do you use the switch and add .ToString()to the type?

或者你使用开关并添加.ToString()到类型?

采纳答案by Anton Gogolev

If I reallyhad to switchon type of object, I'd use .ToString(). However, I would avoid it at all costs: IDictionary<Type, int>will do much better, visitormight be an overkill but otherwise it is still a perfectly fine solution.

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

回答by David Wengier

I'd just use an if statement. In this case:

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

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

The other way to do this is:

另一种方法是:

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

The first example is true for exact types only, where the latter checks for inheritance too.

第一个示例仅适用于精确类型,后者也检查继承。

回答by Dave Van den Eynde

You can do this:

你可以这样做:

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

While that would be more elegant, it's possibly not as efficient as some of the other answers here.

虽然这会更优雅,但它可能不如这里的其他一些答案有效。

回答by sharptooth

One approach is to add a pure virtual GetNodeType() method to NodeDTO and override it in the descendants so that each descendant returns actual type.

一种方法是将纯虚拟 GetNodeType() 方法添加到 NodeDTO 并在后代中覆盖它,以便每个后代返回实际类型。

回答by Jason Coyne

Depending on what you are doing in the switch statement, the correct answer is polymorphism. Just put a virtual function in the interface/base class and override for each node type.

根据您在 switch 语句中的操作,正确的答案是多态性。只需在接口/基类中放置一个虚拟函数并覆盖每个节点类型。

回答by Arnis Lapsa

In the MSDN blog post Many Questions: switch on typeis some information on why .NETdoes not provide switching on types.

在 MSDN 博客文章Many Questions: switch on type 中是关于为什么.NET不提供类型切换的一些信息。

As usual - workarounds always exists.

像往常一样 - 解决方法始终存在。

This one isn't mine, but unfortunately I have lost the source. It makes switching on types possible, but I personally think it's quite awkward (the dictionary idea is better):

这不是我的,但不幸的是我失去了来源。它使切换类型成为可能,但我个人认为这很尴尬(字典的想法更好):

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

Usage:

用法:

 new Switch(foo)
     .Case<Fizz>
         (action => { doingSomething = FirstMethodCall(); })
     .Case<Buzz>
         (action => { return false; })

回答by bjaxbjax

I'm faced with the same problem and came across this post. Is this what's meant by the IDictionary approach:

我遇到了同样的问题,并遇到了这篇文章。这是 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;
    }
}

If so, I can't say I'm a fan of reconciling the numbers in the dictionary with the case statements.

如果是这样,我不能说我喜欢将字典中的数字与案例陈述相协调。

This would be ideal but the dictionary reference kills it:

这将是理想的,但字典参考杀死了它:

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

Is there another implementation I've overlooked?

我忽略了另一个实现吗?

回答by nreyntje

You can do this:

你可以这样做:

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

It's clear and its easy. It a bit slower than caching the dictionary somewhere.. but for lots of code this won't matter anyway..

这很清楚而且很容易。它比在某处缓存字典慢一点..但是对于很多代码来说这无关紧要..

回答by Ashley

This won't directly solve your problem as you want to switch on your own user-defined types, but for the benefit of others who only want to switch on built-in types, you can use the TypeCodeenumeration:

这不会直接解决您的问题,因为您想打开自己的用户定义类型,但为了其他只想打开内置类型的人的利益,您可以使用TypeCode枚举:

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

    case TypeCode.Int32:
        // Handle Int32
        break;
     ...
}

回答by Wayne Phipps

I actually prefer the approach given as the answer here: Is there a better alternative than this to 'switch on type'?

我实际上更喜欢这里给出的答案的方法: 是否有比“打开类型”更好的替代方法?

There is however a good argument about not implementing any type comparison methids in an object oriented language like C#. You could as an alternative extend and add extra required functionality using inheritance.

然而,关于在面向对象的语言(如 C#)中不实现任何类型比较方法的观点是有道理的。作为替代,您可以使用继承来扩展和添加额外的必需功能。

This point was discussed in the comments of the authors blog here: http://blogs.msdn.com/b/jaredpar/archive/2008/05/16/switching-on-types.aspx#8553535

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

I found this an extremely interesting point which changed my approach in a similar situation and only hope this helps others.

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

Kind Regards, Wayne

亲切的问候,韦恩