我正在对double
进行以下演员,并故意回到long
:
var adjustedValue = (long)(double)dateTime.Ticks;
(其中dateTime
是System.DateTime
而Ticks
是long
)。然而,Resharper告诉我,double
的转换是“多余的”,这让我想知道它是否可以被编译器优化掉。
答案 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);
摘要:
它不会优化这种演员方式。