首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

Microsoft C# 編譯器與 Mono C# 編譯器產出 IL 代碼差異分析

     編輯:關於C#

本文透過同一份 C# 程式碼分別在 Windows(Microsoft CSC)與 Linux(Mono GMCS)編譯,並使用 ildasm 反組譯比較產出的 IL 代碼差異。發現 Mono 編譯器產出的 IL 更精簡,Microsoft 編譯器則包含許多看似多餘的指令(如 nop、initobj),且對結構體建構函式中 : this() 的處理截然不同。

測試程式碼 Block.cs

using System;

namespace Skyiv.Ben.Test
{
    struct Block
    {
        public int Id { get; private set; }
        public int Time { get; set; }
        public Block(int id) : this() { Id = id; }
    }

    sealed class Test
    {
        static void Main()
        {
            Console.WriteLine(new Block(37).Time);
        }
    }
}

編譯環境

平台編譯器版本
Windowscsc.exeMicrosoft (R) Visual C# 2008 Compiler 3.5.30729.1
Linux (openSUSE 11.1)gmcsMono C# compiler 2.4.0.0

執行結果

兩組編譯產出的 .exe 在 Windows 與 Linux (Mono) 上執行皆輸出 0(Time 未初始化預設值),跨平台相容性良好。

IL 代碼關鍵差異

1. 屬性定義:多出 instance 修飾詞

Microsoft 編譯器產出的屬性簽章包含 instance,Mono 則無。此為語法糖差異,不影響執行。

2. get_Id 方法:Microsoft 產生大量多餘 IL

  • Microsoft:包含多個 nop、ldarg.0、call 等指令,約 20 行 IL。
  • Mono:極精簡,僅 ldarg.0、ldflda、ldind.i4、ret 共 4 行。

即使未加 /debug+,Microsoft 仍產生這些指令,推測為編譯器內部實作細節。

3. set_Id 方法:雙方完全一致

此處兩編譯器產出相同 IL,顯示非所有情況 Microsoft 都較冗長。

4. 建構函式 .ctor(int):關鍵差異在 initobj

原始碼:public Block(int id) : this() { Id = id; }

  • Microsoft:產生 IL_0001: initobj Skyiv.Ben.Test.Block 呼叫無參數建構函式(對應 : this())。
  • Mono:完全忽略 : this(),不產生 initobj,直接對欄位賦值。

若移除 : this(),Microsoft 編譯報錯(CS0188、CS0843),強制要求呼叫預設建構函式以初始化自動屬性背後欄位;Mono 則編譯通過且執行正常。

實務啟示

作者在 Ubuntu MonoDevelop 開發 ACM 題目時未寫 : this(),Mono 編譯通過;提交至使用 Microsoft 編譯器的評測系統卻編譯失敗。這提醒跨平台開發時需注意編譯器語義差異。

結論

  • Mono C# 編譯器產出的 IL 代碼更精簡、高效,無冗餘 nop、initobj。
  • Microsoft C# 編譯器較嚴格遵循語言規範(強制 : this() 初始化自動屬性),但產生較多 IL 指令。
  • 實際執行效能差異微乎其微(JIT 最佳化會消除大部分差異),但 IL 體積與可讀性上 Mono 佔優。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved