相同的IL代码,不同的输出 - 如何可能?

Hal*_*ali 9 .net c# mono cil

我有一段代码,它根据C#编译器和运行时输出不同的结果.

有问题的代码是:

using System;

public class Program {
    public static void Main() {
        Console.WriteLine(string.Compare("alo\0alo\0", "alo\0alo\0\0", false, System.Globalization.CultureInfo.InvariantCulture));
    }
}
Run Code Online (Sandbox Code Playgroud)

结果是:

                    Compiling with mono (gmcs)    Compiling with .Net (csc)
Running with mono                           -1                           -1
Running with .Net                           -1                            0
Run Code Online (Sandbox Code Playgroud)

当使用.Net框架运行时,它如何输出不同的值?

(顺便说一句,根据http://msdn.microsoft.com/en-us/library/system.string.aspx,输出应该是0,所以mono的答案是不正确的,但这与我的问题无关.)

甚至生成的IL代码也(几乎)相同.

用.Net编译:

.method public hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       29 (0x1d)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldstr      bytearray (61 00 6C 00 6F 00 00 00 61 00 6C 00 6F 00 00 00 ) // a.l.o...a.l.o...
  IL_0006:  ldstr      bytearray (61 00 6C 00 6F 00 00 00 61 00 6C 00 6F 00 00 00   // a.l.o...a.l.o...
                                  00 00 ) 
  IL_000b:  ldc.i4.0
  IL_000c:  call       class [mscorlib]System.Globalization.CultureInfo [mscorlib]System.Globalization.CultureInfo::get_InvariantCulture()
  IL_0011:  call       int32 [mscorlib]System.String::Compare(string,
                                                              string,
                                                              bool,
                                                              class [mscorlib]System.Globalization.CultureInfo)
  IL_0016:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_001b:  nop
  IL_001c:  ret
} // end of method Program::Main
Run Code Online (Sandbox Code Playgroud)

用mono编译:

.method public hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       27 (0x1b)
  .maxstack  8
  IL_0000:  ldstr      bytearray (61 00 6C 00 6F 00 00 00 61 00 6C 00 6F 00 00 00 ) // a.l.o...a.l.o...
  IL_0005:  ldstr      bytearray (61 00 6C 00 6F 00 00 00 61 00 6C 00 6F 00 00 00   // a.l.o...a.l.o...
                                  00 00 ) 
  IL_000a:  ldc.i4.0
  IL_000b:  call       class [mscorlib]System.Globalization.CultureInfo [mscorlib]System.Globalization.CultureInfo::get_InvariantCulture()
  IL_0010:  call       int32 [mscorlib]System.String::Compare(string,
                                                              string,
                                                              bool,
                                                              class [mscorlib]System.Globalization.CultureInfo)
  IL_0015:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_001a:  ret
} // end of method Program::Main
Run Code Online (Sandbox Code Playgroud)

唯一的区别是.Net版本中的两个额外NOP指令.

这怎么可能?两个输出值如何不同?

此外,如果有人同时安装了.Net和单声道,你可以重现它吗?

编辑:我不关心正确的结果是什么,我不在乎 mono和.Net产生不同的结果.我可能永远不会遇到嵌入的空值并对它们进行排序,排序顺序很重要.

我的问题是相同的运行时间(.NET 2.0)产生不同的结果,当编译的由不同的编译器.

编辑2:我添加了一个表格并尝试澄清问题,现在应该更容易理解.

Jon*_*eet 3

我的猜测是,当您使用 Mono 编译它时,它引用了 .NET 2.0 版本的 mscorlib - 而当您使用 VS 编译它时,它的目标是 .NET 4.0。

对于每种情况下的具体目标版本,我可能不正确,但这就是我想要开始的地方:不要查看该方法的 IL,而应查看引用的程序集。

(顺便说一句,如果你能说出你安装了哪些版本的 VS、.NET 和 Mono,这可能会有所帮助。)

编辑:好的,所以如果无论您的目标版本是什么,它都会做同样的事情,那么对每个版本上运行 ildasm 的结果运行差异怎么样?比较整个文件,而不仅仅是方法调用本身的 IL。