Yakın zamanda TryRoslyn'de C# derleyicisi ile oynuyordum ve bir eşitsizlik kontrolünün birden fazlaya dönüştürüldüğü garip bir soruna rastladım. İşte üreme kodu:Neden Roslyn, burada bir> karşılaştırma yerine> bir karşılaştırma üretiyor?
using System;
public class C {
public void M() {
if (Foo() != 0 || Foo() != 0)
{
Console.WriteLine("Hi!");
}
}
private int Foo() => 0;
}
ve burada decompiler tarafından oluşturulan alır koddur: repro için
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 bağlantı. Roslyn bunu neden yapıyor? bu bir hata mı?
Bazı gözlemler Bir süre koduyla etrafında oynadıktan sonra yaptık:
Bu yalnızca durumda son boolean ifade ile olur. Örneğin, başka bir
||
bildirimi eklerseniz, yalnızca son çağrıFoo()
ile gerçekleşir.Ayrıca özellikle 0 ile olur;
1
veya başka bir sayı için değiştirirseniz, bu olmaz.
Tamam, sanırım sorunun ne olduğunu görüyorum; opcode unsigned bir karşılaştırma yapar bir 'cgt.un', bu yüzden decompiled kodu gerçekten '(uint) bu olmalıdır.Foo()> (uint) 0' (tüm sıfır olmayan inters için doğru olan). Bunu işaret ettiğin için teşekkürler. –
@JamesKo: Kesinlikle doğru! –