将泛型类型参数显式转换为任何接口 [英] explicitly cast generic type parameters to any interface
问题描述
在 泛型常见问题解答:最佳实践中说:
编译器允许您将泛型类型参数显式转换为任何接口,但不能转换为类:
The compiler will let you explicitly cast generic type parameters to any interface, but not to a class:
interface ISomeInterface
{...}
class SomeClass
{...}
class MyClass<T>
{
void SomeMethod(T t)
{
ISomeInterface obj1 = (ISomeInterface)t;//Compiles
SomeClass obj2 = (SomeClass)t; //Does not compile
}
}
我认为类和接口的限制都是合理的,除非类/接口未指定为约束类型.
I see limitation reasonable for both, classes and interfaces, unless the class/interface is not specified as constraint type.
那么为什么这种行为,为什么它被允许用于接口?
So why such behavior, why it is allowed for interfaces ?
推荐答案
我相信这是因为转换到 SomeClass
可能意味着任何数量的事情,这取决于可用的转换,而转换到ISomeInterface
只能是引用转换或装箱转换.
I believe this is because the cast to SomeClass
can mean any number of things depending on what conversions are available, whereas the cast to ISomeInterface
can only be a reference conversion or a boxing conversion.
选项:
首先投射到对象:
Cast to object first:
SomeClass obj2 = (SomeClass) (object) t;
使用 as
代替:
SomeClass obj2 = t as SomeClass;
显然,在第二种情况下,如果 t
是 not 一个 SomeClass
,您还需要在之后执行无效检查.
Obviously in the second case you would also need to perform a nullity check afterwards in case t
is not a SomeClass
.
C# 4 规范的第 6.2.7 节给出了原因:
The reasoning for this is given in section 6.2.7 of the C# 4 specification:
上述规则不允许从不受约束的类型参数直接显式转换为非接口类型,这可能令人惊讶.这条规则的原因是为了防止混淆并使此类转换的语义清晰.例如,考虑以下声明:
The above rules do not permit a direct explicit conversion from an unconstrained type parameter to a non-interface type, which might be surprising. The reason for this rule is to prevent confusion and make the semantics of such conversions clear. For example, consider the following declaration:
class X<T>
{
public static long F(T t) {
return (long)t; // Error
}
}
如果允许将 t 直接显式转换为 int,人们可能很容易期望 X
将返回 7L.但是,它不会,因为只有在绑定时已知类型为数字时才考虑标准数字转换.为了使语义清楚,上面的例子必须改为:
If the direct explicit conversion of t to int were permitted, one might easily expect that X<int>.F(7)
would return 7L. However, it would not, because the standard numeric conversions are only considered when the types are known to be numeric at binding-time. In order to make the semantics clear, the above example must instead be written:
class X<T>
{
public static long F(T t) {
return (long)(object)t; // Ok, but will only work when T is long
}
}
此代码现在可以编译,但执行 X
会在运行时抛出异常,因为装箱的 int 不能直接转换为 long.>
This code will now compile but executing X<int>.F(7)
would then throw an exception at run-time, since a boxed int cannot be converted directly to a long.
这篇关于将泛型类型参数显式转换为任何接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!