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

C# 使用Case/Switch和GetType确定对象,c#,.net,reflection,switch-statement,case,C#,.net,Reflection,Switch Statement,Case,可能重复: 如果要在对象类型上切换,最好的方法是什么 代码片段 我知道这样不行,但我想知道你怎么解决这个问题。 在这种情况下,if/else语句是否合适 或者您是否使用开关并将.ToString()添加到类型?如果我确实必须对对象类型进行开关,我会使用.ToString()。然而,我会不惜一切代价避免它:IDictionary会做得更好,可能是一个过火的解决方案,但否则它仍然是一个完美的解决方案。我只会使用if语句。在这种情况下: Type nodeType=node.GetType();

可能重复:

如果要在对象类型上切换,最好的方法是什么

代码片段 我知道这样不行,但我想知道你怎么解决这个问题。 在这种情况下,
if/else
语句是否合适


或者您是否使用开关并将
.ToString()
添加到类型?

如果我确实必须对对象类型进行
开关,我会使用
.ToString()
。然而,我会不惜一切代价避免它:
IDictionary
会做得更好,可能是一个过火的解决方案,但否则它仍然是一个完美的解决方案。

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

Type nodeType=node.GetType();
if(nodeType==typeof(CasusNodeDTO))
{
}
其他的
另一种方法是:

if(节点是CasusNodeDTO)
{
}
其他的
第一个示例仅适用于精确类型,后者也检查继承。

您可以这样做:

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

虽然这会更加优雅,但它可能没有这里的其他一些答案那么有效。

一种方法是向NodeTo添加纯虚拟GetNodeType()方法,并在子体中重写它,以便每个子体返回实际类型。

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

在MSDN博客文章中提供了一些关于为什么不提供打开类型的信息

像往常一样,解决办法总是存在的

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

公共类开关
{
公用交换机(对象o)
{
对象=o;
}
公共对象对象{get;private set;}
}
/// 
///扩展,因为在开关==null上外壳失效
/// 
公共静态类扩展
{
公共静态开关箱(此开关s,动作a)
T:在哪里上课
{
返回案例(s,o=>true,a,false);
}
公共静态开关箱(该开关s,动作a,
bool fallThrough)其中T:class
{
返回案例(s,o=>true,a,fallThrough);
}
公共静态开关箱(此开关s,
Func c,动作a)其中T:class
{
返回案例(s、c、a、false);
}
公共静态开关箱(此开关s,
函数c,动作a,布尔故障诊断)其中T:class
{
如果(s==null)
{
返回null;
}
T=s。对象为T;
如果(t!=null)
{
if(c(t))
{
a(t);
返回故障?s:null;
}
}
返回s;
}
}
用法:

 new Switch(foo)
     .Case<Fizz>
         (action => { doingSomething = FirstMethodCall(); })
     .Case<Buzz>
         (action => { return false; })
新开关(foo)
案例
(action=>{doingSomething=FirstMethodCall();})
案例
(操作=>{return false;})

我也面临着同样的问题,因此偶然发现了这篇文章。 这就是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 (node is CasusNodeDTO)
{
    ...
}
else if (node is BucketNodeDTO)
{
    ...
}
...
function void PrintType(Type t) {
 var t = true;
 new Dictionary<Type, Action>{
   {typeof(bool), () => Console.WriteLine("bool")},
   {typeof(int),  () => Console.WriteLine("int")}
 }[t.GetType()]();
}
函数无效打印类型(类型t){
var t=真;
新词典{
{typeof(bool),()=>Console.WriteLine(“bool”)},
{typeof(int),()=>Console.WriteLine(“int”)}
}[t.GetType()]();
}
这很清楚,也很容易。
这比在某处缓存字典要慢一点。。但是对于很多代码来说,这并不重要。

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

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

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

实际上,我更喜欢这里给出的答案:

然而,关于不在面向对象语言(如C#)中实现任何类型比较方法,有一个很好的论据。您也可以使用继承扩展和添加额外的必需功能

这一点在作者博客的评论中进行了讨论:

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


您好,在我看来,Wayne

i词典是一个很好的解决方案。如果要测试的类型不止一种或两种,我通常会使用它。好吧,或者首先使用多态性来避免打开类型。适当的多态性。如果将此“类型”用于序列化,那么您可能会有各种各样的顾虑。为什么不努力并给出一个IDictionary在所述情况下的应用示例?我支持这一点,但我认为比较引用要比重复强制转换尝试快。不过,我不确定比较引用的速度。我认为RuntimeType系统开始生效了。我只是猜测,因为如果不是那样的话,编译器不会告诉你typeof(X)不是常数第二个类型检查速度较慢,因为它检查整个类层次结构。虽然这是处理它的OO方法,您可能会决定该节点不必支持任何这些。这里有一个大+1,对Jason Coyne来说。没有其他人读过重构这本书吗?这是一个教科书上的例子:如果有人感兴趣,Peter Hallam会讨论为什么这不是C#at的一个特征,我知道这是2017年,这是一个古老的评论……但刚刚读了Peter Hallam的那篇文章,我现在感到困惑。C#7允许在case语句的顺序很重要的地方切换-这肯定是冲突的,因为这似乎是他没有添加到语言中的主要原因之一?实际上,你可以在C#7中切换类型…我猜他们改变了主意(或者想出了更好的方法)12年后:相关评论:VB.NET具有此功能
switch (Type.GetTypeCode(node.GetType()))
{
    case TypeCode.Decimal:
        // Handle Decimal
        break;

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