C#编译器能否优化此抛弃?

Asi*_*sik 0 c#

我做了以下投地double,并回long,故意:

var adjustedValue = (long)(double)dateTime.Ticks;
Run Code Online (Sandbox Code Playgroud)

(dateTimea System.DateTimeTicksa 在哪里long).然而Resharper告诉我,演员double是"多余的",这让我想知道它是否可以被编译器优化掉.

p.s*_*w.g 8

我在LINQPad中尝试了这段代码:

var dateTime = DateTime.Now;
var adjustedValue = (long)(double)dateTime.Ticks;
adjustedValue.Dump();
Run Code Online (Sandbox Code Playgroud)

无论是否优化,它都会生成相同的IL(唯一的区别在于标签):

IL_0000:  call        System.DateTime.get_Now
IL_0005:  stloc.0     // dateTime
IL_0006:  ldloca.s    00 // dateTime
IL_0008:  call        System.DateTime.get_Ticks
IL_000D:  conv.r8     
IL_000E:  conv.i8     
IL_000F:  stloc.1     // adjustedValue
IL_0010:  ldloc.1     // adjustedValue
IL_0011:  call        LINQPad.Extensions.Dump
Run Code Online (Sandbox Code Playgroud)

所以答案是否定的,C#编译器没有优化这个双重演员.即使启用了优化,转换仍然存在.

但是,您还应该注意到,此双重转换显着改变原始数据.这是一个使用LINQPad创建的快速演示:

var dateTime = DateTime.Now;
var originalValue = dateTime.Ticks;
var adjustedValue = (long)(double)originalValue;
originalValue.Dump(); // 635385353415288655
adjustedValue.Dump(); // 635385353415288704
Run Code Online (Sandbox Code Playgroud)

这是因为double只有15-16位精度,但a long可能长达19位.你一定会得到一些舍入错误.如果这是一个问题,您可以使用decimal替代.这样可以避免任何舍入错误,但即使在这种情况下,C#编译器也不会对双重转换进行优化.

当然,JIT编译器或NGen.exe如何将其转换为本机代码是完全不同的事情,但我希望行为是相同的.