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

C# 在C中使用as关键字与泛型类型冲突的编译时行为#,c#,generics,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 F

当试图对无法转换为的非泛型类型使用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
   }
}
公共类Foo{}
公共类Bar{}
公共类用法{
公开无效测试(){
EventArgs args=新的EventArgs();
var foo=args as foo;//编译器错误:无法转换类型
var bar=args as bar;//没有编译器错误
}
}
我在一个更大的代码库中发现了这种行为,在这个代码库中,编译时错误的缺失导致了运行时的问题

冲突行为是故意的吗?如果是,有人知道原因吗?

“请注意,as运算符只执行引用转换、可为null的转换和装箱转换。as运算符不能执行其他转换,例如用户定义的转换,而应该使用强制转换表达式来执行这些转换。”


第7.10.11节中,as操作员
C#5.0规范规定:

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

  • 标识(§6.1.1)、隐式可空(§6.1.4)、隐式引用(§6.1.6)、装箱(§6.1.7)、显式可空(§6.2.3)、显式 参考(§6.2.4)或拆箱(§6.2.5)从E转换为 T

  • E型或T型为开放型。

  • E是空文本

因此,
args as Foo
给出了一个错误,因为这些都不是真的。但在第二种情况下,
条形图
是一种开放式类型,规范将开放式类型解释为,
§4.4.2开放式和封闭式类型

开放式类型是指包含类型参数的类型。更具体地说:

  • 类型参数定义打开类型。[……]

这并不能解释为什么
args as Bar
不会给出任何编译器错误。仅供参考:R#会用警告“可疑强制转换:解决方案中没有从'EventArgs'和'Bar'继承的类型”@juharr谢谢!我想这表明这个问题在C#中是可以检测到的。我还针对F#编译器仔细检查了这个问题,它像R#一样拾取无效的强制转换(但在F#的情况下,它被标记为错误),我只是在规范中找到了它,但不确定在这种情况下开放类型的特殊性是什么。谢谢!这回答了“设计的冲突行为”的问题,答案是肯定的。关于为什么的见解似乎是对您在文档中提到的表达式的翻译的天真实现。但我应该指出,我不能100%确定这是真的。这是我能想到的唯一合乎逻辑的解释。根据你所说的,我不认为它被翻译成
args is Bar?(Bar)(object)args:(Bar)nullargs
类型为
dynamic
,而不是。我还没有得到规范(没有安装office),所以我只是解释二手资料。