Sel*_*enç 17 .net c# casting dynamic as-operator
我刚刚发布了这个问题的答案,但我并不完全相信我的答案.我想知道有两件事,请考虑以下代码:
class Foo<T>
{
void SomeMethod()
{
string str = "foo";
Foo<T> f = str as Foo<T>;
}
}
Run Code Online (Sandbox Code Playgroud)
据说C# Specification 5.0,有两种不同的转换方式as operator.
如果编译时类型
E不是dynamic,则操作E as T产生与之相同的结果Run Code Online (Sandbox Code Playgroud)E is T ? (T)(E) : (T)null如果编译时类型
E是dynamic,则与as operator强制转换运算符不同,它不是动态绑定的(第7.2.2节).因此,在这种情况下的扩展是:Run Code Online (Sandbox Code Playgroud)E is T ? (T)(object)(E) : (T)null
因为,这是无效的 (Foo<T>)str
str is Foo<T> ? (Foo<T>)str : (Foo<T>)null;
Run Code Online (Sandbox Code Playgroud)
我认为它应该被翻译为:
str is Foo<T> ? (Foo<T>)(object)str : (Foo<T>)null;
Run Code Online (Sandbox Code Playgroud)
但是,规范说,当类型这只是发生E的dynamic.
所以我的问题是:
E是动态的,所以首先它转换E到object随后T尽管(T)E是完全有效的?Yuv*_*kov 12
编译器是否将此表达式转换为通常无效的代码?
在盯着规范大约一个小时之后,我开始说服自己这只是一个边缘案例,在规范中被忽略了.请注意,这仅仅是C#语言编写者用as运算符的语义表达运算符的一种方式is.
编译器实际上并没有将as运算符转换为带有的三元运算符is.它将发出一个IL调用isinst,as以及和is:
IL_0000: nop
IL_0001: ldstr "foo"
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: isinst class ConsoleApplication2.Foo`1<!T>
IL_000d: stloc.1
IL_000e: ret
Run Code Online (Sandbox Code Playgroud)
查看已编译的DLL,as运算符保持不变.
当E的类型是动态的时候,为什么首先它将E转换为对象然后T,而(T)E完全有效?
这在规范的细则中有所描述:
如果E的编译时类型是动态的,与转换运算符不同,as运算符不是动态绑定的(第7.2.2节).因此,在这种情况下的扩展是:
E is T ? (T)(object)(E) : (T)null
Run Code Online (Sandbox Code Playgroud)
对演员object是需要做出使用的as可能的dynamic对象.as是一个编译时操作,而dynamic对象仅在运行时绑定.
编译器实际上将dynamic类型对象视为object开头的类型:
class Foo<T>
{
public void SomeMethod()
{
dynamic str = "foo";
Foo<T> f = str as Foo<T>;
}
}
Run Code Online (Sandbox Code Playgroud)
str实际上被视为object开头:
.class private auto ansi beforefieldinit Foo`1<T>
extends [mscorlib]System.Object
{
// Methods
.method public hidebysig
instance void SomeMethod () cil managed
{
// Method begins at RVA 0x2050
// Code size 15 (0xf)
.maxstack 1
.locals init (
[0] object,
[1] class Foo`1<!T>
)
IL_0000: nop
IL_0001: ldstr "foo"
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: isinst class Foo`1<!T>
IL_000d: stloc.1
IL_000e: ret
} // end of method Foo`1::SomeMethod
}
Run Code Online (Sandbox Code Playgroud)
在与Managed Languages Team的Vladimir Reshetnikov交谈之后,他解释了从"as operator"到"cast operator"的表示语义实际上是什么意思:
我同意,规范中也有一些不精确的语言.它表示'as'运算符始终适用于涉及的开放类型,但随后描述了其在演员表方面的评估,在某些情况下可能无效.这应该说在扩张蒙上那并不代表正常的C#转换操作符,但只是表示允许在"为"经营者的转换.我会记下来解决它.谢谢!
| 归档时间: |
|
| 查看次数: |
283 次 |
| 最近记录: |