Stavo giocando con il compilatore C# su TryRoslyn di recente, e mi sono imbattuto in uno strano problema in cui un controllo di disuguaglianza si stava trasformando in uno più grande di uno. Ecco il codice di Repro:Perché Roslyn genera un confronto> anziché un! = Uno qui?
using System;
public class C {
public void M() {
if (Foo() != 0 || Foo() != 0)
{
Console.WriteLine("Hi!");
}
}
private int Foo() => 0;
}
e qui è il codice che viene generato dal decompilatore:
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 il link al Repro. Perché Roslyn fa questo; E 'un errore?
Alcune osservazioni che ho fatto dopo aver giocato con il codice per un po ':
accade questo solo con l'ultima espressione booleana nella condizione. Ad esempio, se aggiungi un'altra istruzione
||
, ciò avverrà solo con l'ultima chiamata aFoo()
.Inoltre verifica solo con 0, in particolare; se lo sostituisci per
1
, o qualche altro numero, non succederà.
OK, penso di vedere qual è il problema; l'opcode è un 'cgt.un', che esegue un confronto senza segno, quindi il codice decompilato dovrebbe in realtà essere' (uint) this.Foo()> (uint) 0' (che è vero per tutti gli interi non zero). Grazie per la segnalazione. –
@JamesKo: Esattamente! –