我试图了解编译器对非常简单的代码所做的工作:
if (group.ImageHeight > 1 && group.ImageWidth > 1)
{ //No code exists between the braces
}
以Debug
配置进行编译后,然后进行反编译,我看到以下内容:
if (group.ImageHeight <= 1 || group.ImageWidth <= 1);
反编译Release
配置会导致
if (group.ImageHeight > 1)
{
int imageWidth = group.ImageWidth;
}
更完整的(原始)代码:
public class Group
{
public int ImageHeight { get; set; }
public int ImageWidth { get; set; }
}
//The following belongs to a different project than `Group`
static void Main(string[] args)
{
Group group = new Group();
MyMethod(group);
}
static void MyMethod(Group group)
{
if (group.ImageHeight > 1 && group.ImageWidth > 1)
{
}
}
这是我到目前为止的猜测和发现:
group
类型属于我的解决方案中的另一个项目很重要。我之所以这样说,是因为编译器可能无法“知道”将来评估属性的副作用。例如,我可以在编译后替换包含group
定义的DLL。Release
配置中,可能的副作用似乎与我的代码相同:对ImageHeight
进行了评估,如果满足> 1
条件将对ImageWidth
进行评估(尽管通过分配而不是比较)现在,对于我的具体问题:
Release
配置使用分配(int imageWidth = group.ImageWidth
)而不是我的原始比较?运行作业更快吗?Debug
配置完全改变了副作用的可能性?在此配置中,ImageHeight
和ImageWidth
都将始终被评估。 答案 0 :(得分:3)
For the first specific question. When you look at IL on sharplab.io The simple assignment is 1 compare instruction short. Whose "then" and "else" would point to the same instruction (in this case IL_0012) so compare there is not needed for calling function and two pops are enough. Weird is only loading the Int32 constant 1 which will be discarded immidiately.
if (group.ImageHeight > 1)
IL_0000: ldarg.0
IL_0001: callvirt instance int32 Group::get_ImageHeight()
IL_0006: ldc.i4.1
IL_0007: ble.s IL_0012
int imageWidth = group.ImageWidth;
IL_0009: ldarg.0
IL_000a: callvirt instance int32 Group::get_ImageWidth()
IL_000f: ldc.i4.1
IL_0010: pop
IL_0011: pop
IL_0012: ret
For second specific question. If you look at IL on the same page with Debug mode, you'll see, that the code is identical only with some additional instructions for debuging and the compare itself so you can watch the result of it in debuger.
IL_0000: nop
IL_0001: ldarg.0
IL_0002: callvirt instance int32 Group::get_ImageHeight()
IL_0007: ldc.i4.1
IL_0008: ble.s IL_0015
IL_000a: ldarg.0
IL_000b: callvirt instance int32 Group::get_ImageWidth()
IL_0010: ldc.i4.1
IL_0011: cgt
IL_0013: br.s IL_0016
IL_0015: ldc.i4.0
IL_0016: stloc.0
// sequence point: hidden
IL_0017: ldloc.0
IL_0018: brfalse.s IL_001c
IL_001a: nop
IL_001b: nop
IL_001c: ret