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

Conflicting compile time behaviour using as keyword against generic types in C#

当尝试对无法转换为的非泛型类型使用 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
   }
}

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

冲突行为是设计使然吗?如果是这样,有人知道为什么吗?

"Note that the as operator performs only reference conversions, nullable conversions, and boxing conversions. The as operator can't perform other conversions, such as user-defined conversions, which should instead be performed by using cast expressions."

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

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

In an operation of the form E as T, E must be an expression and T must be a reference type, a type parameter known to be a reference type, or a nullable type. Furthermore, at least one of the following must be true, or otherwise a compile-time error occurs:

  • An identity (§6.1.1), implicit nullable (§6.1.4), implicit reference (§6.1.6), boxing (§6.1.7), explicit nullable (§6.2.3), explicit reference (§6.2.4), or unboxing (§6.2.5) conversion exists from E to T.

  • The type of E or T is an open type.

  • E is the null literal.

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

An open type is a type that involves type parameters. More specifically:

  • A type parameter defines an open type. [...]