C#和其他的.NET編程語言有一個叫作Caller Information Attribute的概念。在參數上應用這些屬性時,開發人員就可以不負責提供匹配參數,把這些事情留給了編譯器。目前,C#支持文件名或路徑、行號以及調用方法或屬性名的Caller Information Attribute。根據“Caller Expression Attribute”提案,表達式也將支持Caller Information Attribute。
考慮以下這對斷言:
Assert.IsTrue(x - 7 > 0);
Assert.IsTrue(y - 3 > 0);
如果測試失敗,很難確定是哪個斷言被觸發。你可以爲每個斷言提供一條消息,但這樣做很枯燥乏味,而且很容易就過時,如果表達本身可以被捕獲就好了。
public static void IsTrue(bool condition, [CallerArgumentExpression("condition")] string message = null);
在這個示例中,如果開發人員未明確提供消息,那麼編譯器會將會使用condition參數對應的代碼。本質上,編譯器將代碼轉換爲如下所示的形式:
Assert.IsTrue(x - 7 > 0, "x - 7 > 0");
Assert.IsTrue(y - 3 > 0, "y - 3 > 0");
根據提案的設計,這種捕獲機制甚至可以被用在擴展方法上。
潛在的問題
這個設計存在三個問題。
如果提供的參數是null或者不是參數名的字符串,那麼編譯器將傳入一個空字符串。
知道如何使用反編譯器的人將能夠通過反編譯看到標有這個屬性的方法的一些源代碼。對於閉源軟件來說,這可能是難以接受的。
雖然這不是功能本身的缺陷,但問題是現在存在一個只接受bool的Debug.Assert API。即使重載方法的第二個參數使用了這個屬性,並且是可選的,編譯器仍然會選擇非消息的那個參數。因此,非消息重載會被移除,這將造成二進制(儘管不是源代碼)的突破性變更。
狀態
目前,Caller Expression Attribute被列在C# 8路線圖中,狀態爲“Prototype”。
查看英文原文:https://www.infoq.com/news/2019/01/Caller-Expression-Attribute