我问了这个问题.由于这里解释的原因(即使我期望在运行时而不是编译时错误),此代码无法编译("无法转换Generic<T>为T").InvalidCastException
class NonGeneric
{
}
class Generic<T> : NonGeneric
where T : NonGeneric
{
T DoSomething()
{
return (T)this; // ** Cannot convert...
}
}
Run Code Online (Sandbox Code Playgroud)
接受的解决方案给出了这个解决方法:
T DoSomething()
{
return this as T;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:为什么?as运算符应该完全等同于强制运算符:
as运算符就像一个强制转换操作.但是,如果无法进行转换,则返回null而不是引发异常.
如果this as T应该等于this is T? (T)this: (T)null那么为什么as T工作,(T)this甚至不编译?AFAIK演员阵容可用于更广泛的情况as:
请注意,as运算符仅执行引用转换,可空转换和装箱转换.as运算符不能执行其他转换,例如用户定义的转换,而应使用转换表达式执行转换.
那为什么呢?它是as操作员的记录功能吗?它是泛型类型的编译器/语言限制吗?请注意,此代码编译正常:
return (T)((object)this);
Run Code Online (Sandbox Code Playgroud)
这是因为编译器不能确定是否T是dynamic(即使是有where约束),那么它会永远产生这样的代码?
根据msdn: -
as运算符就像一个强制转换操作.但是,如果无法进行转换,则返回null而不是引发异常
代码等效于以下表达式,只是表达式变量仅被计算一次.
expression is type ? (type)expression : (type)null
Run Code Online (Sandbox Code Playgroud)
另一个不同之处在于: -
请注意,as运算符仅执行引用转换,可空转换和装箱转换.as运算符不能执行其他转换,例如用户定义的转换,而应使用转换表达式执行转换.
它在C#语言规范(强调我的)中说,
如果E的编译时类型不是动态的,那么作为T的操作E产生与E是T相同的结果?(T)(E):( T)null,除了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节) 0.4),或取消装箱(§6.2.5)转换,从存在
E于T.• 类型
E或是T开放类型.•
E是null文字.
这是您的泛型类的当前案例.
| 归档时间: |
|
| 查看次数: |
266 次 |
| 最近记录: |