今天在修改一個既有程式時,用上了 System.Runtime.CompilerServices 命名空間裡的 CallerMemberNameAttribute。
這次碰到的狀況,正巧是 CallerMemberNameAttribute 適用的場合:在某個方法中,取得呼叫此方法的那個物件的方法或屬性的名稱。
舉個例子,假設我們要寫一個共用的工具類別,取名為 TracerHelper,其用途是輸出呼叫端的屬性或方法名稱。
用戶端每次呼叫時,都必須傳入固定的字串,例如底下這個 Customer 類別:
那麼,每當我們存取 Customer 物件的 FullName 屬性,以及呼叫 Test 方法時,執行結果會像這樣:
問題是,每一次呼叫 TracerHelper.ShowCallerMember() 方法就得寫一個固定的字串,萬一將來想要修改方法或屬性名稱,很可能因為忘了一併修改傳入 ShowCallerMember 方法的參數而導致程式執行結果錯誤。此時,CallerMemberNameAttribute 便可派上用場。
CallerMemberNameAttribute 是 .NET 4.5 與 C# 5.0 之後才有的新功能。此特徵項只能套用至非必要參數(optional parameters),也就是有指定預設值的參數。
先前的 TraceHelper.ShowCallerMember 方法可以改成這樣:
如此一來,剛才的 Customer 類別可修改成:
現在已經沒有固定的字串了。編譯器在編譯代碼時會幫我們取出呼叫端的方法或屬性名稱,作為 TraceHelper.ShowCallerMember() 的傳入參數。
這是編譯時期發生的事,所以並不會增加執行時期的效能負擔。
除了 [CallerMemberName],另外還有兩個類似的特徵項,也是套用於方法的傳入參數:
Happy coding!
這次碰到的狀況,正巧是 CallerMemberNameAttribute 適用的場合:在某個方法中,取得呼叫此方法的那個物件的方法或屬性的名稱。
舉個例子,假設我們要寫一個共用的工具類別,取名為 TracerHelper,其用途是輸出呼叫端的屬性或方法名稱。
static class TraceHelper { public static void ShowCallerMember(object obj, string memberName) { Console.WriteLine("Caller member is: {0}.{1}.", obj.GetType().Name, memberName); } }
用戶端每次呼叫時,都必須傳入固定的字串,例如底下這個 Customer 類別:
class Customer { private string _fullName; public void Test() { TraceHelper.ShowCallerMember(this, "Test"); } public string FullName { get { TraceHelper.ShowCallerMember(this, "FullName"); return _fullName; } } }
那麼,每當我們存取 Customer 物件的 FullName 屬性,以及呼叫 Test 方法時,執行結果會像這樣:
Caller member is: Customer.FullName. Caller member is: Customer.Test.
問題是,每一次呼叫 TracerHelper.ShowCallerMember() 方法就得寫一個固定的字串,萬一將來想要修改方法或屬性名稱,很可能因為忘了一併修改傳入 ShowCallerMember 方法的參數而導致程式執行結果錯誤。此時,CallerMemberNameAttribute 便可派上用場。
CallerMemberNameAttribute 是 .NET 4.5 與 C# 5.0 之後才有的新功能。此特徵項只能套用至非必要參數(optional parameters),也就是有指定預設值的參數。
先前的 TraceHelper.ShowCallerMember 方法可以改成這樣:
static class TraceHelper { public static void ShowCallerMember(object obj, [CallerMemberName] string memberName"") // 只改這行! { Console.WriteLine("Caller member is: {0}.{1}.", obj.GetType().Name, memberName); } }
如此一來,剛才的 Customer 類別可修改成:
class Customer { private string _fullName; public void Test() { TraceHelper.ShowCallerMember(this); } public string FullName { get { TraceHelper.ShowCallerMember(this); return _fullName; } } }
現在已經沒有固定的字串了。編譯器在編譯代碼時會幫我們取出呼叫端的方法或屬性名稱,作為 TraceHelper.ShowCallerMember() 的傳入參數。
這是編譯時期發生的事,所以並不會增加執行時期的效能負擔。
除了 [CallerMemberName],另外還有兩個類似的特徵項,也是套用於方法的傳入參數:
- [CallerFilePath]:取得呼叫端所屬的原始碼檔案的完整路徑。
- [CallerLineNumber]:取得呼叫端的程式碼行號。
Happy coding!
沒有留言: