使用 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."
在 §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. [...]
当尝试对无法转换为的非泛型类型使用 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."
在 §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. [...]