在前幾篇文章中,我們已經探討了 C# 方法重載的基本概念與 IL 層面的表現。本文將深入剖析當方法參數為 null 時,編譯器如何根據「最精確匹配」原則選擇調用目標。
using System;
public class Program
{
public static void Main()
{
Show(null);
Show("");
Show(1);
}
static void Show(Object o)
{
Console.WriteLine("Object");
}
static void Show(String s)
{
Console.WriteLine("String");
}
}
String
Object
Object
從 IL 角度看,string s = null; 對應指令 ldnull。雖然 null 可以視為任何引用類型的「空值」,但 C# 的重載解析規則傾向於選擇最具體(最派生)的類型。因為 String 繼承自 Object,所以 Show(String) 比 Show(Object) 更精確,編譯器因此綁定後者。
這類似於「身高分組」的邏輯:主持人說「身高不到 1.60m 的坐前排,不到 1.75m 的坐中排」。身高 1.55m 的人雖然同時滿足兩個條件,但自然會選擇最嚴格(最精確)的那一組。同理,null 在類型層級上最貼近 String,故調用 Show(String)。
Show("") 等價於 string s = ""; Show(s);。變量 s 的靜態類型為 string,因此直接匹配 Show(String),印證了「參數最匹配優先」的原則。
1 是 int,無隱式轉換至 string,只能向上轉型為 object,故調用 Show(Object)。
null 沒有運行時類型,編譯期按靜態類型推斷,優先匹配最具體的簽名。