为什么Roslyn会生成一个>比较而不是!=一个在这里?

时间:2016-06-08 04:21:32

标签: c# .net roslyn

我最近在TryRoslyn上玩C#编译器,我遇到了一个奇怪的问题,即不等式检查被转换为大于一的。这是repro代码:

using System;
public class C {
    public void M() {
        if (Foo() != 0 || Foo() != 0)
        {
            Console.WriteLine("Hi!");
        }
    }

    private int Foo() => 0;
}

以下是反编译器生成的代码:

using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
[assembly: AssemblyVersion("0.0.0.0")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[module: UnverifiableCode]
public class C
{
    public void M()
    {
        bool flag = this.Foo() != 0 || this.Foo() > 0; // this should be an != check
        if (flag)
        {
            Console.WriteLine("Hi!");
        }
    }
    private int Foo()
    {
        return 0;
    }
}

Here's指向repro的链接。为什么罗斯林会这样做;这是一个错误吗?

在玩了一段时间之后,我已经做了一些观察:

  • 这只发生在条件中的最后一个布尔表达式。例如,如果您添加另一个||语句,则只会在最后一次调用Foo()时发生。

  • 它也只发生在0,具体而言;如果您将其替换为1或其他一些数字,则不会发生。

1 个答案:

答案 0 :(得分:11)

反编译代码错误;这是反编译器中的错误,而不是编译器。生成的IL是正确的。 非常仔细阅读IL 。你明白为什么大于比较是正确的并且反编译是错误的吗?

至于为什么这个codegen只发生在操作员的右侧,我不记得了。如果你想在代码生成器中进行探索,那就在这里:

https://github.com/dotnet/roslyn/blob/master/src/Compilers/CSharp/Portable/CodeGen/EmitOperators.cs

您需要方法EmitIsNonNullOrZero