上一篇我們討論了 null 的匹配行為。本文通過一個具體例子,進一步揭示 C# 重載解析時依據的是變量的聲明類型(引用類型),而非對象的實際運行時類型(實例類型)。
using System;
namespace OverrideDemo
{
class Program
{
static void Main(string[] args)
{
String s = null;
Show(s); // 調用 Show(string)
Object o = "123";
Show(o); // 調用 Show(object)
}
static void Show(string s) { Console.WriteLine("String"); }
static void Show(Object o) { Console.WriteLine("Object"); }
}
}
String
Object
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 1
.locals init ([0] string s, [1] object o)
IL_0000: nop
IL_0001: ldnull
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: call void OverrideDemo.Program::Show(string)
IL_0009: nop
IL_000a: ldstr "123"
IL_000f: stloc.1
IL_0010: ldloc.1
IL_0011: call void OverrideDemo.Program::Show(object)
IL_0016: nop
IL_0017: ret
}
String s = null; 中 s 的聲明類型是 string,雖然運行時值為 null,但編譯器根據靜態類型選擇 Show(string)。這證明重載解析在編譯期完成,依賴變量的靜態類型。
Object o = "123"; 這裡 o 的聲明類型是 object,雖然它引用一個 string 實例,但調用的是 Show(object)。說明 C# 不 根據對象的實際類型(實例類型)進行重載分發,這與虛擬方法的多態行為不同。
| 特性 | 虛擬方法 | 重載方法 |
|---|---|---|
| 分發時機 | 運行時 | 編譯時 |
| 依據 | 實例類型 | 聲明(引用)類型 |
| 關鍵字 | virtual/override | 無特殊關鍵字 |