为什么'是'实现'作为'?

2023-09-03 09:55:23 作者:感情像一阵风

考虑到这是一个很自然的用例(如果你不知道什么实际上做),

 如果(x是吧){
   酒吧Y = X,酒吧;
   某物();
}
 

实际上相当于(也就是编译器生成的 CIL 从上面的code会遭到相当值)为:

 酒吧Y = X,酒吧;
如果(Y!= NULL){
    Y = X,酒吧; //转换比例的两倍!
    某物();
}
 

编辑:

我想我还没有作出我的问题清楚。我不会永远写入第二个片段,因为它的当然是多余的。林声称通过编译所述第一代码段时,编译器生成的CIL是等同于第二片段,这是多余的。问题:1)这是正确的? B)如果是这样,为什么实施这样呢?

Vlog日常尝鲜 想学美食博主做一期美美的火锅视频,结果手忙脚乱处处翻车

这是因为我找到的第一个片段更加清晰和prettier比实际精心编写

 酒吧Y = X,酒吧;
如果(Y!= NULL){
   某物();
}
 

结论:

优化 / 的情况是不是编译器的责任,但JIT的。

此外,与空检查它比两个备选方案(较少的(更便宜)的说明铸造)。

附录:

CIL为与nullcheck(.NET 3.5):

  L_0001:ldarg.1
L_0002:isinst字符串
L_0007:stloc.0
L_0008:ldloc.0
L_0009:ldnull
L_000a:CEQ
L_000c:stloc.1
L_000d:ldloc.1
L_000e:brtrue.s L_0019
L_0011:ldarg.0
L_0019:RET
 

CIL的是和铸造(.NET 3.5):

  L_0001:ldarg.1
L_0002:isinst字符串
L_0007:ldnull
L_0008:cgt.un
L_000a:ldc.i4.0
L_000b:CEQ
L_000d:stloc.1
L_000e:ldloc.1
L_000f:brtrue.s L_0021
L_0012:ldarg.1
L_0013:castclass字符串
L_0018:stloc.0
L_0019:ldarg.0
L_0021:RET
 

CIL的,是和作为(.NET 3.5):

  L_0001:ldarg.1
L_0002:isinst字符串
L_0007:ldnull
L_0008:cgt.un
L_000a:ldc.i4.0
L_000b:CEQ
L_000d:stloc.1
L_000e:ldloc.1
L_000f:brtrue.s L_0021
L_0012:ldarg.1
L_0013:isinst字符串
L_0018:stloc.0
L_0019:ldarg.0
L_0021:RET
 

这些已经被编辑过急促(方法声明,NOP指令并调用的东西()删除)。

解决方案   

A)这是正确的。

是的,但我会说,它的其他方式。您是说是,是一个语法糖作为-随访,由空检查。我会说,它的其他方式:即作为是一个语法糖检查类型的实现,如果投成功,如果失败空

这就是说,我会更倾向于说

 如果(x是吧){
   酒吧Y = X,酒吧;
   某物();
}
 

实际上相当于

 如果(x是吧){
   条Y =(x是吧)? (棒)×:(棒)空;
   某物();
}
 

见,要在以下方面界定为,是,而不是其他的方式。真正的问题应该是为什么为实现吗? : - )

  

二)如果是这样,为什么是这样实现的?

由于这是正确实施规范。

我想我没听懂你的思想路线在这里。有什么不妥的实施?你会如何​​preFER它来执行?你有isinst和castclass在您的处置指令;描述codeGEN为你的程序,你想看到的。

Given that this is a very natural use case (if you don't know what as actually does),

if (x is Bar) {
   Bar y = x as Bar;
   something();
}

is effectively equivalent (that is, the compiler-generated CIL from the above code will be equivalent) to:

Bar y = x as Bar;
if (y != null) {
    y = x as Bar; //The conversion is done twice!
    something();
}

EDIT:

I guess I hadn't made my question clear. I wouldn't ever write the second snippet as it's of course redundant. I'm claiming that the CIL generated by the compiler when compiling the first snippet is equivalent to the second snippet, which is redundant. Questions: a) Is this correct? b) If so, why is is implemented like that?

This is because I find the first snippet a lot clearer and prettier than the actually well-written

Bar y = x as Bar;
if (y != null) {
   something();
}

CONCLUSION:

Optimizing the is/as case is not the compiler's responsibility, but the JIT's.

Also, as with a null check it has fewer (and less expensive) instructions than both of the alternatives (is and as and is and cast).

Addendum:

CIL for as with nullcheck (.NET 3.5):

L_0001: ldarg.1
L_0002: isinst string
L_0007: stloc.0
L_0008: ldloc.0
L_0009: ldnull
L_000a: ceq
L_000c: stloc.1
L_000d: ldloc.1
L_000e: brtrue.s L_0019
L_0011: ldarg.0
L_0019: ret

CIL for is and cast (.NET 3.5):

L_0001: ldarg.1
L_0002: isinst string
L_0007: ldnull
L_0008: cgt.un
L_000a: ldc.i4.0
L_000b: ceq
L_000d: stloc.1
L_000e: ldloc.1
L_000f: brtrue.s L_0021
L_0012: ldarg.1
L_0013: castclass string
L_0018: stloc.0
L_0019: ldarg.0
L_0021: ret

CIL for is and as (.NET 3.5):

L_0001: ldarg.1
L_0002: isinst string
L_0007: ldnull
L_0008: cgt.un
L_000a: ldc.i4.0
L_000b: ceq
L_000d: stloc.1
L_000e: ldloc.1
L_000f: brtrue.s L_0021
L_0012: ldarg.1
L_0013: isinst string
L_0018: stloc.0
L_0019: ldarg.0
L_0021: ret

These have been edited for shortness (method declarations, nops and calls to something() removed).

解决方案

a) Is this correct

Yes, though I would have stated it the other way. You are saying that "is" is a syntactic sugar for as-followed-by-null-check. I would have said it the other way: that "as" is a syntactic sugar for "check for type implementation, cast if success, null if failure".

That is to say, I would be more inclined to say

if (x is Bar) { 
   Bar y = x as Bar; 
   something(); 
} 

is effectively equivalent to

if (x is Bar) { 
   Bar y = (x is Bar) ? (Bar)x : (Bar) null; 
   something(); 
} 

See, you want to define "as" in terms of "is", not the other way around. The question really should be "why is as implemented as is?" :-)

b) If so, why is is implemented like that?

Because that's a correct implementation of the specification.

I think I'm not following your line of thought here. Is there something wrong with that implementation? How would you prefer it to be implemented? You have the "isinst" and "castclass" instructions at your disposal; describe the codegen for your program that you'd like to see.

相关推荐