程式世界兩大隱性元素:協議(動態、執行期、不確定)與 約束(靜態、編譯期、確定)。靜態語言側重約束,動態語言側重協議。C# 融合兩者優勢,得動靜結合之美。
void B()
{
ArrayList list = A(); // 協議:A 回傳的 ArrayList 內部皆為 string
foreach (string s in list) Console.WriteLine(s.Length);
}
此協議 無編譯器保護,A 可塞入非 string 導致 B 運行期炸裂。
void B()
{
List list = A(); // 編譯期保證元素型別
foreach (string s in list) Console.WriteLine(s);
}
單方法介面與委託常被視為等價,實則 約束強度截然不同:
委託擁有更多「協議性」,靈活得多。
interface ILogger { void Write(string msg); }
class A { public ILogger Logger { get; set; } void F() {} }
class B { void G() { var a = new A(); a.Logger = new LogAdapter(); a.F(); } }
class LogAdapter : ILogger { void Write(string msg) { ThirdPartyLogger.Log(msg); } }
class A { public Action Logging { get; set; } void F() {} }
class B { void G() { var a = new A(); a.Logging = msg => ThirdPartyLogger.Log(msg); a.F(); } }
委託版本:無新增類別、無型別耦合、僅需簽名匹配。介面約束強、委託約束弱、委託更靈活。
後續將探討 Duck Typing、泛型委託妙用、表達式樹與 Lambda、.NET 4.0 動態編程等主題。