为什么C#switch语句不允许使用typeof / GetType()?

时间:2009-11-10 20:34:58

标签: c# .net reflection switch-statement

如本例所示:

switch ( myObj.GetType ( ) )
{
    case typeof(MyObject):
        Console.WriteLine ( "MyObject is here" );
        break;
}

10 个答案:

答案 0 :(得分:19)

第二篇关于彼得哈勒姆的帖子;这是一个很好的解释。

但是,您可以使用TypeCode处理简单类型。

switch (Type.GetTypeCode(myObj.GetType())) {
    case TypeCode.Boolean: ...
    case TypeCode.Char: ...
    case TypeCode.String: ...
    case TypeCode.Object: ...
    default: ...
} 

答案 1 :(得分:14)

我会在彼得的优秀分析中加入以下思想:

基本上,“切换”的目的是选择一些不同的可能性。给定的枚举值,整数,布尔值或字符串类型只能是一个值,因此“切换”这样的值是有意义的。但类型根本不同。给定值通常具有多个类型。类型经常重叠。建议的“类型开关”与开关结构的所述目的不匹配。

答案 2 :(得分:13)

问题在于switch(根据规范)仅适用于基元(int等)和字符串。但是,它会很好to have F#-style matching

来自§8.7.2:

switch-label:
   case   constant-expression   :
   default   :
     

...   switch语句的控制类型由switch表达式建立。   如果switch表达式的类型是sbyte,byte,short,ushort,int,uint,long,   ulong,char,string或enum-type,那么这就是switch的管理类型   声明。否则,必须存在一个用户定义的隐式转换(第6.4节)   switch表达式的类型为以下可能的管理类型之一:   sbyte,byte,short,ushort,int,uint,long,ulong,char,string。如果没有这样的隐含   存在转换,或者如果存在多个这样的隐式转换,则为编译时   发生错误。

然而,很明显,使用这种受限制的集合可以实现简单(和有效)的IL。请注意,string通过字典映射处理为整数。

答案 3 :(得分:5)

good blog post on MSDN by Peter Hallam解释了切换非常数值的问题。

  

“案例标签的顺序变为   在确定哪个块时有重要意义   代码被执行。因为   案例标签表达不是   常量编译器无法验证   案例标签的值是   不同,所以这是一种可能性   必须照顾到。这样运行   与大多数程序员的直觉相反   关于一对中的switch语句   方式大多数程序员都会   惊讶地发现改变了   他们的案件块的顺序改变了   他们的计划的意义。转过来   如果是的话,那将是令人惊讶的   正在接通的表达是平等的   到案例标签中的表达式,但是   控制没有去那个标签。“

答案 4 :(得分:4)

你可以做到

switch ( myObj.GetType().Name )
{
    case "MyObject":
        Console.WriteLine ( "MyObject is here" );
        break;
}

这是有效的,因为切换仅适用于原始类型(正如其他人所说)。

答案 5 :(得分:2)

这是typeof不是常量,case必须是常量。

答案 6 :(得分:2)

C#中的开关仅适用于积分或字符串。 myObj.GetType()返回一个Type,它既不是整数,也不是字符串。

答案 7 :(得分:1)

你为什么不把它串起来呢?

答案 8 :(得分:0)

在C#7.0中,你可以做到。看到 Pattern Matching in C# 7.0 Case Blocks

SELECT * 
FROM SalesMonth(10, 2001) M10
INNER JOIN SalesMonth(9, 2001) M9
ON    M10.ProductId = M9.ProductID
WHERE M10.SumPrice > M9.SumPrice;

答案 9 :(得分:-2)

除了懒惰之外,MS没有充分的理由不实现切换类型。

字符串切换是使用“if(.. Equals(..))”来完成的,只有很少的情况和一个包含许多情况的字典。这两种方法都是针对所有.NET类型定义的,因为System.Object具有虚拟的Equals和GetHashCode。

可以说,“切换可以使用任何类型的表达式,其中Equals和GetHashCode被覆盖”,这会自动限定字符串,类型等。是的,错误的Equals / GetHashCode实现会破坏switch语句,但是,嘿,你也可以打破“==”运算符,“foreach”循环,以及其他一些东西,所以我真的没有看到程序员错误导致开关被打破的“大问题”。但即使他们不想为所有类型允许它,无论出于何种原因,当然Type是安全的,因为Type.Equals()定义良好,并且也实现了GetHashCode。

另外,我不认为你考虑继承的论点; switch转到其常量(和类型(int)是常量,不要误会)的情况等于表达式 - 继承是Type类型的另一个“行为”。一个甚至不需要考虑继承,我的意思是,我们拒绝比较2个对象只是因为它们具有其他特性吗?不,我们不这样做,因为总是定义平等。基本上,重点是,不同类型之间没有重叠。

正如我所说,只有一个原因和一个原因:懒惰。 :)