c# - C# 'is' 运算符是否会在 .NET 4 的 Release模式优化下受到影响?

标签 c# optimization compiler-construction il

下面是一个简单的测试夹具。它在调试构建中成功并在发布构建中失败(VS2010、.NET4 解决方案、x64):

[TestFixture]
public sealed class Test
{
    [Test]
    public void TestChecker()
    {
        var checker = new Checker();
        Assert.That(checker.IsDateTime(DateTime.Now), Is.True);
    }
}

public class Checker
{
    public bool IsDateTime(object o)
    {
        return o is DateTime;
    }
}

代码优化似乎造成了一些破坏;如果我在发布版本中禁用它,它也能正常工作。这让我很费解。下面,我使用 ILDASM 反汇编了构建的 2 个版本:

调试 IL:

.method public hidebysig instance bool IsDateTime(object o) cil managed
{
  // Code size       15 (0xf)
  .maxstack  2
  .locals init (bool V_0)
  IL_0000:  nop
  IL_0001:  ldarg.1
  IL_0002:  isinst     [mscorlib]System.DateTime
  IL_0007:  ldnull
  IL_0008:  cgt.un
  IL_000a:  stloc.0
  IL_000b:  br.s       IL_000d
  IL_000d:  ldloc.0
  IL_000e:  ret
} // end of method Validator::IsValid

发布 IL:

.method public hidebysig instance bool IsDateTime(object o) cil managed
{
  // Code size       10 (0xa)
  .maxstack  8
  IL_0000:  ldarg.1
  IL_0001:  isinst     [mscorlib]System.DateTime
  IL_0006:  ldnull
  IL_0007:  cgt.un
  IL_0009:  ret
} // end of method Validator::IsValid

似乎优化了存储和负载。针对早期版本的 .NET 框架使问题消失,但这可能只是侥幸。我发现这种行为有些令人不安,谁能解释为什么编译器会认为进行产生不同可观察行为的优化是安全的?

提前致谢。

最佳答案

此错误已在 this SO question 中出现雅各布·斯坦利。雅各布已经reported the bug ,并且微软已经确认这确实是 CLR JIT 中的一个错误。微软是这样说的:

This bug will be fixed in a future version of the runtime. I'm afraid it's too early to tell if that will be in a service pack or the next major release.

Thank you again for reporting the issue.

您应该能够通过将以下属性添加到 TestChecker() 来解决此错误:

[MethodImpl(MethodImplOptions.NoInlining)]

关于c# - C# 'is' 运算符是否会在 .NET 4 的 Release模式优化下受到影响?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5543692/

相关文章:

c# - 处理用户控件,真的意味着编辑 .designer.cs 文件吗?

c# - 当外部库不向后兼容时检查属性是否存在

scala - 优雅的AST模型

c++ - 在函数定义中有条件地执行计算的最佳方法

c++ - 直接从 COleDateTime 获取年份和月份还是先转换为 SYSTEMTIME 更快?

c - sdcc 不接受代码

c - 将指针传递给 C 中的指针

c# - 我可以克隆一个 IQueryable 以在另一个 DbContext 的 DbSet 上运行吗?

c# - 当 Byte 溢出时实际发生了什么?

c# - 如何防止 JIT 编译器优化此方法