I asked 这个问题 https://stackoverflow.com/questions/21432141/why-i-cannot-cast-derived-generic-type-to-base-non-generic-type-through-a-const。此代码无法编译(“无法转换Generic<T>
to T
")因为解释的原因here https://stackoverflow.com/a/21432252/1207195(即使我期望InvalidCastException
在运行时代替编译时错误)。
class NonGeneric
{
}
class Generic<T> : NonGeneric
where T : NonGeneric
{
T DoSomething()
{
return (T)this; // ** Cannot convert...
}
}
接受的解决方案提供了此解决方法:
T DoSomething()
{
return this as T;
}
我的问题是:why? as
运算符应该与强制转换运算符完全相同:
as 运算符类似于强制转换操作。但是,如果无法进行转换,as 将返回 null 而不是引发异常。
If this as T
应该等于this is T? (T)this: (T)null
那么为什么as T
作品和(T)this
甚至无法编译? AFAIKcast 的使用范围比as
:
请注意,as 运算符仅执行引用转换、可为空转换和装箱转换。 as 运算符无法执行其他转换,例如用户定义的转换,而应使用强制转换表达式来执行这些转换。
那为什么会这样呢?这是一个已记录的功能吗as
操作员?这是泛型类型的编译器/语言限制吗?请注意,此代码编译良好:
return (T)((object)this);
这是因为编译器无法确定是否T
is dynamic
(即使有一个where
约束)那么它总是会生成这样的代码?
它在 C# 语言规范(强调我的)中说,
如果 E 的编译时类型不是动态的,则 E as T 操作会产生与以下相同的结果
E 是 T 吗? (T)(E) : (T)空
只不过 E 只被评估一次。编译器可以将 E 优化为 T 来最多执行一次动态类型检查,而不是上面的扩展所隐含的两次动态类型检查。
如果 E 的编译时类型是dynamic
,与强制转换运算符不同as
运算符不是动态绑定的(第 7.2.2 节)。因此本例中的展开式为:E is T ? (T)(object)(E) : (T)null
这似乎是使用编译成功的原因as
或当this
首先被转换为一个对象。此外,
在形式的操作中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
to T
.
• 的类型E
or T
是开放式的。
• E
is the null
文字。
这是您的泛型类的当前情况。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)