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

12 浏览
0 Comments

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

就像这个例子一样:

switch ( myObj.GetType ( ) )
{
    case typeof(MyObject):
        Console.WriteLine ( "这里有MyObject" );
        break;
}

0
0 Comments

C# 的 switch 语句不允许使用 typeof/GetType() 的原因是什么?有什么解决方法呢?

在 Peter Hallam 的帖子中,第二个问题有一个很好的解释。尽管如此,你仍然可以使用 TypeCode 来处理简单类型。

以下是使用 TypeCode 来测试简单类型的示例代码:

switch (Type.GetTypeCode(myObj.GetType())) {
    case TypeCode.Boolean:
        // 处理布尔类型
        break;
    case TypeCode.Char:
        // 处理字符类型
        break;
    case TypeCode.String:
        // 处理字符串类型
        break;
    case TypeCode.Object:
        // 处理对象类型
        break;
    default:
        // 处理其他类型
        break;
}

那么如何测试枚举类型呢?有没有什么办法呢?

0
0 Comments

C#的switch语句为什么不允许使用typeof/GetType()?这个问题的出现主要是因为switch语句的本质目的是从一系列不同的可能性中选择一个。而枚举、整数、布尔值或字符串类型的给定值只能是一个值,所以在这些值上使用switch语句是有意义的。但是类型是根本不同的,给定的值通常有很多类型,这些类型经常重叠。因此,提出的“类型切换”与switch语句的目的不符。

某些情况下vb.net可以做到这一点,那它是如何工作的呢?它是对vb.net性能的妥协还是与C#的switch语句不同的一种结构?

VB的官方文档中写明了这个构造,文档链接为:msdn.microsoft.com/en-us/library/cy37t14y.aspx。从上面的链接可以看出,对于testexpression(测试表达式),VB构造的文档说:“必需的。表达式。必须求值为基本数据类型之一(Boolean、Byte、Char、Date、Double、Decimal、Integer、Long、Object、SByte、Short、Single、String、UInteger、ULong和UShort)”。所以,与C#一样,VB.NET也不允许任何东西作为Select...Case语句的测试表达式。

“给定的值通常有很多类型”-这完全没有任何意义。.NET中的每个值只有一个类型,它继承自什么,是一个基类,是否具有通用参数都是无关紧要的。

C#的switch语句不允许使用typeof/GetType()是因为类型与枚举、整数、布尔值或字符串类型的值的性质不同。要解决这个问题,可以考虑使用其他语言如VB.NET中的Select...Case语句来实现相同的功能。

0
0 Comments

为什么C#的switch语句不允许使用typeof/GetType()?这个问题的出现原因是因为C#的switch语句只能用于原始类型(如int等)和字符串,根据规范。从§8.7.2:

switch-label:
   case   constant-expression   :
   default   :
...
  switch语句的控制类型由switch表达式确定。
  如果switch表达式的类型是sbyte、byte、short、ushort、int、uint、long、ulong、char、string或枚举类型,则该类型是switch语句的控制类型。否则,从switch表达式的类型到以下可能的控制类型中的一个之间必须存在一个用户定义的隐式转换(§6.4):
  sbyte、byte、short、ushort、int、uint、long、ulong、char、string。如果不存在这样的隐式转换,或者存在多个这样的隐式转换,则会发生编译时错误。

然而,显然,使用这样的受限集合进行简单(和高效)的IL操作是有问题的。请注意,字符串是通过一个映射到整数的字典来处理的。

答案很明显,如果他们使用字典来处理字符串,为什么微软不用字典来处理其他类型呢?

然而,vb.net允许在switch中使用任何东西,因为它只对编译时常量(如字符串文字)起作用。关键字在IL代码中使用,因此需要在编译时知道。

形式为`typeof(SomeType)`的表达式也是常量,但是不允许使用。也许`typeof(T)`或`typeof(SomeType)`(泛型)仍然被禁止,因为在编译时无法检查唯一性,但是除此之外,任何类型都应该是合法的。

这个问题不是什么是可能的。因为一切都是可能的。问题是为什么你不能使用typeof运算符,而答案是因为它不是编译时常量。它是调用一个依赖于`RuntimeTypeHandle`参数的方法的简写,而在调用带有运行时参数的方法时没有编译时常量,typeof不能被编译时常量,因为它不适用于泛型,也不适用于动态类型或动态创建的代码。所有这些都是C#的一部分。

C#定义了`typeof`运算符,它的实现方式并不重要。同样,`switch`语句也是如此。在没有泛型的情况下,从C#的角度来看,`typeof` case块是有意义的。这是唯一要考虑的。问题是,为什么在C#中是非法的,答案是除了优先级较低和有解决方法可用之外,没有更强有力的理由,可以在字符串的情况下使用switch,if语句等。

`GetType()`是一个方法,所以你显然对问题的解释与我不同,这个讨论是没有意义的,因为我们在比较不同的东西。

`switch`语句本身中的表达式可以调用`GetType()`或任何其他方法/属性,这一点是无关紧要的。问题是关于`case`语句是否具有`typeof()`运算符。`typeof()`和`obj.GetType()`之间存在着很大的区别。

对于你来说是有区别的,对我来说没有。无论被调用的方法是GetType还是GetTypeFromHandle,无论它是静态方法还是实例方法,对我来说都没有太大区别。

`“语言”(C#)和它的实现方式(.NET IL)之间存在差异。对于特定的语言结构,被写出的内容并不重要;我们无论对我还是对你来说,都不相关。问题是关于语言的,当讨论它时,我们应该坚持讨论语言结构。

0