2016-06-08 25 views
7

我玩弄于TryRoslyn C#编译器最近,我穿过一个奇怪的问题,其中一个不等式检查渐渐转变成一个大于一个人来。这里是摄制代码:为什么Roslyn在这里生成一个>比较而不是!=一个?

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链接到摄制。为什么罗斯林会这样做;这是一个错误?

一些意见我已经有一段代码玩耍后提出:

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

  • 它也只以0发生,特别;如果您将其替换为1或其他数字,则不会发生。

回答

11

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

至于为什么这codegen只发生在操作员的右侧,我不记得。如果你想要去的代码生成洞穴探险它是在这里:

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

你想方法EmitIsNonNullOrZero

+0

好吧,我想我看到的问题是什么;操作码是一个'cgt.un',这确实一个无符号的比较,所以反编译的代码真正应该'(UINT)this.Foo()>(UINT)0'(这是对于所有非零整数真)。感谢您指出了这一点。 –

+0

@JamesKo:没错! –

相关问题