我问this question。此代码无法编译(“无法将Generic<T>
转换为T
”),因为解释here的原因(即使我期望{{3}} 1}}在运行时而不是编译时错误。)
InvalidCastException
接受的解决方案给出了解决方法:
class NonGeneric
{
}
class Generic<T> : NonGeneric
where T : NonGeneric
{
T DoSomething()
{
return (T)this; // ** Cannot convert...
}
}
我的问题是:为什么? T DoSomething()
{
return this as T;
}
运算符应完全等同于强制运算符:
as运算符就像一个强制转换操作。但是,如果无法进行转换,则返回null而不是引发异常。
如果as
应该等同于this as T
那么为什么this is T? (T)this: (T)null
有效且as T
甚至无法编译? AFAIK演员阵容可用于比(T)this
更广泛的情况:
请注意,as运算符仅执行引用转换,可空转换和装箱转换。 as运算符无法执行其他转换,例如用户定义的转换,而应使用强制转换表达式执行转换。
那为什么呢?它是as
运算符的文档功能吗?它是泛型类型的编译器/语言限制吗?请注意,此代码编译良好:
as
这是因为编译器无法确定return (T)((object)this);
是否为T
(即使存在dynamic
约束),那么它是否会始终生成此类代码?
答案 0 :(得分:5)
根据msdn: -
as运算符就像一个强制转换操作。但是,如果无法进行转换,则返回null而不是引发异常
代码等同于以下表达式,只是表达式变量只被计算一次。
expression is type ? (type)expression : (type)null
另一个不同之处在于: -
请注意,as运算符仅执行引用转换,可空转换和装箱转换。 as运算符无法执行其他转换,例如用户定义的转换,而应使用强制转换表达式执行转换。
答案 1 :(得分:5)
它在C#语言规范(强调我的)中说,
如果E的编译时类型不是动态的,则作为T的操作E产生与之相同的结果 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
必须是引用类型,已知为引用类型的类型参数或可空类型。此外,必须至少满足下列条件之一,否则会发生编译时错误:•标识(第6.1.1节),隐式可空(第6.1.4节),隐式引用(第6.1.6节),装箱(第6.1.7节),显式可空(第6.2.3节),显式引用(§6.2.4)或从
E
到T
的拆箱(§6.2.5)转换。•
E
或T
的类型是开放式。•
E
是null
字面值。
您的通用类的当前案例。
答案 2 :(得分:-5)
'as'作为C#中的运算符执行以下操作: -
'as'运算符比任何一个转换都快一些(即使在没有无效转换的情况下,由于异常会严重降低转换的性能)。