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

时间:2014-06-16 21:22:07

标签: c#

我正在对double进行以下演员,并故意回到long

var adjustedValue = (long)(double)dateTime.Ticks;

(其中dateTimeSystem.DateTimeTickslong)。然而,Resharper告诉我,double的转换是“多余的”,这让我想知道它是否可以被编译器优化掉。

2 个答案:

答案 0 :(得分:8)

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

var dateTime = DateTime.Now;
var adjustedValue = (long)(double)dateTime.Ticks;
adjustedValue.Dump();

无论有无优化,它都会生成相同的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

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

但是,您还应注意到此双重 会显着更改原始数据。这是一个快速演示,也是使用LINQPad创建的:

var dateTime = DateTime.Now;
var originalValue = dateTime.Ticks;
var adjustedValue = (long)(double)originalValue;
originalValue.Dump(); // 635385353415288655
adjustedValue.Dump(); // 635385353415288704

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

当然,JIT编译器或NGen.exe convert this to native code如何完全不同,但我希望行为是相同的。

答案 1 :(得分:1)

我刚检查出来。使用“dotPeek 1.1”,我“看了一下”这个源代码。

使用配置Debug它保持原样,因为未设置/ optimize标志。 使用配置版本确实发生了一些变化,但不是演员表。在Release中,默认情况下,/ optimize开关已打开。

var adjustedValue = (long)(double)DateTime.Now.Ticks;

Console.WriteLine(adjustedValue);

去了

Console.WriteLine((long) (double) DateTime.Now.Ticks);

摘要:

它不会优化这种演员方式。