C# “的意外行为”;作为「;运算符,它不同于普通转换
我问。由于解释的原因,此代码无法编译(“无法将C# “的意外行为”;作为「;运算符,它不同于普通转换,c#,.net,casting,C#,.net,Casting,我问。由于解释的原因,此代码无法编译(“无法将泛型转换为t”)(即使我希望在运行时出现无效异常,而不是编译时错误) 我的问题是:为什么as运算符应与cast运算符完全等效: as运算符类似于强制转换操作。但是,如果转换不可能,as将返回null而不是引发异常 如果这作为T应该等同于这是T?(T) 这:(T)null那么为什么因为T起作用而(T)这甚至不编译?AFAIK cast可用于比as更广泛的情况: 请注意,as运算符仅执行引用转换、可为null的转换和装箱转换。as运算符不能执行其他转换,
泛型
转换为t
”)(即使我希望在运行时出现无效异常
,而不是编译时错误)
我的问题是:为什么<代码>as运算符应与cast运算符完全等效:
as运算符类似于强制转换操作。但是,如果转换不可能,as将返回null而不是引发异常
如果这作为T
应该等同于这是T?(T) 这:(T)null
那么为什么因为T
起作用而(T)这
甚至不编译?AFAIK cast可用于比as
更广泛的情况:
请注意,as运算符仅执行引用转换、可为null的转换和装箱转换。as运算符不能执行其他转换,例如用户定义的转换,而应该使用强制转换表达式执行这些转换
那为什么呢?它是as
操作员的记录功能吗?它是泛型类型的编译器/语言限制吗?请注意,此代码可以很好地编译:
return (T)((object)this);
这是因为编译器无法确定t
是否是动态的(即使在中存在约束),那么它将始终生成这样的代码?根据:-
as运算符类似于强制转换操作。但是,如果转换不可能,as将返回null而不是引发异常
该代码与以下表达式等效,只是表达式变量只计算一次
另一个区别是:-
请注意,as运算符仅执行引用转换、可为null的转换和装箱转换。as运算符不能执行其他转换,例如用户定义的转换,而应该使用强制转换表达式执行这些转换
它在C语言规范(emphasis mine)中说
如果编译时类型E不是动态的,那么操作E as T将产生与相同的结果
E是T吗?(T) (E):(T)无效
除了E只计算一次。编译器可以将E优化为T,以执行最多一个动态类型检查,而不是上面扩展所暗示的两个动态类型检查
如果E的编译时类型为动态
,则与cast运算符不同,as
运算符不动态绑定(§7.2.2)。因此,这种情况下的扩展是:
E是T吗?(T) (对象)(E):(T)空
这似乎是使用as
或将此
首先强制转换到对象时编译成功的原因。此外,
在形式为E as T
的操作中,E
必须是表达式,T
必须是引用类型、已知为引用类型的类型参数或可为空的类型。此外,必须至少满足以下条件之一,否则会发生编译时错误:
•标识(§6.1.1)、隐式可空(§6.1.4)、隐式引用(§6.1.6)、装箱(§6.1.7)、显式可空(§6.2.3)、显式引用(§6.2.4)或取消装箱(§6.2.5)存在从E
到T
的转换
•类型E
或T
为开放式。
•E
是null
文本
这是泛型类的当前情况。C#中的“as”操作符执行以下操作:-
如果给定变量不是其任何基类型的给定类型,则返回null。它不会抛出任何异常
只能与引用类型变量一起应用
“as”不进行任何转换(隐式/显式)
“as”运算符比任何强制转换都要快一些(即使在没有无效强制转换的情况下,也会由于异常而严重降低强制转换的性能)。编译错误表示您正在继承非通用的。是编译器混淆了,还是代码示例不准确?DoSomething()
函数是否返回T
对象或null
?@KeithPayne抱歉,错误消息。fixed@Adriano你能澄清你的问题为什么吗?为什么?@Adriano:related:-1不,这是我所期望的,但它不是等价的,因为(类型)表达式甚至无法编译。这就是为什么我的问题…它无法编译,因为编译器知道强制转换将失败(在编译时),但在as
的情况下,它可以选择返回null(如果强制转换失败),因此它可以成功编译。不,强制转换可能在运行时失败。它不应该拒绝它(另一种情况请参见编辑)。至少它应该拒绝cast和“as”操作符……在我的例子中,它不是动态的,但我想编译器不会因此而抱怨!非常感谢。头奖我很确定MSDN文档没有包含这个小细节。为什么强调动态
?我不知道DLR是如何涉及到这里的。因为在这种情况下(表达式是动态的
或者,我假设,泛型的
),在转换为t
之前,as
操作符将首先将表达式转换为对象
。它解释了为什么使用作为表达式
或(T)((对象)表达式)
是允许的,而(T)表达式
是不允许的。@RitchMelton是的,即使不应该,因为这里我们只有泛型,没有动态,如果没有其他东西的话……我想这是编译器的问题。。。
T DoSomething()
{
return this as T;
}
return (T)((object)this);
expression is type ? (type)expression : (type)null