使用as关键字对C#中的泛型类型进行编译时行为冲突

时间:2015-01-26 12:14:29

标签: c# generics

当尝试对无法转换的非泛型类型使用C#“as”关键字时,编译器会给出一个无法转换类型的错误。

但是,当对泛型类型使用“as”关键字时,编译器不会给出错误:

public class Foo { }

public class Bar<T> { }

public class Usage<T> {
   public void Test() {
      EventArgs args = new EventArgs();
      var foo = args as Foo;     // Compiler Error: cannot convert type
      var bar = args as Bar<T>;  // No compiler error
   }
}

我在更大的代码库中发现了这种行为,其中缺少编译时错误导致运行时出现问题。

设计是否存在冲突行为?如果是这样,有没有人知道为什么?

2 个答案:

答案 0 :(得分:8)

§7.10.11 The as operator C#5.0规范中说:

  

在E形式的操作中,E必须是表达式,T必须是引用类型,已知为引用类型的类型参数或可空类型。此外,必须至少满足下列条件之一,否则会发生编译时错误:

     
      
  • 标识(第6.1.1节),隐式可空(第6.1.4节),隐式引用(第6.1.6节),装箱(第6.1.7节),显式可空(第6.2.3节),明确的   从E到,存在引用(第6.2.4节)或拆箱(第6.2.5节)转换   吨。

  •   
  • E或T的类型是开放式。

  •   
  • E是空文字。

  •   

所以args as Foo给出错误,因为这都不是真的。但在第二种情况下,Bar<T>是一种开放式,而规范将开放式解释为§4.4.2 Open and closed types

  

开放类型是涉及类型参数的类型。更具体地说:

     
      
  • 类型参数定义开放类型。 [...]
  •   

答案 1 :(得分:-3)

“请注意,as运算符仅执行引用转换,可空转换和装箱转换.as运算符无法执行其他转换,例如用户定义的转换,而应使用强制转换表达式执行转换。”< / p>

https://msdn.microsoft.com/en-us/library/cscsdfbt.aspx