C# 8新提案讓泛型Attribute成為現實

weixin_34127717發表於2019-01-28

從一開始, Attribute就是.NET的一部分。因此,它們在引入泛型之前就已經被建立好,這意味著如果要引用屬性中的型別,必須暴露一個Type引數或屬性。例如:

[TypeConverter(typeof(X))]

這種模式存在一些限制。在上面的示例中,X必須有一個無引數的建構函式,並繼承TypeConverter。編譯器不會強制這些,所以開發人員只能在執行時發現錯誤。

相反,如果我們使用泛型型別引數,那麼就可以在編譯器強制執行這些規則,而且語法會稍微清晰一些。

[TypeConverter\u0026lt;X\u0026gt;]

理論上,“Allow Generic Attributes”提案是一個非常簡單的變更。CLR已經支援這個概念,問題是如何在.NET語言中使用它。但有時候理論和現實是兩條平行線,而且即使CLR可以支援,並不代表就一定會支援。Jan Kotas解釋說:

我認為這個問題的本質與區域性引用和return類似。區域性引用和return不受任何API的限制,理論上它們在現有的執行時、工具和庫上都能正常執行。但在實際當中,它們可能不能正常執行,因為它們暴露了預先存在的錯誤和限制,可能是因為它們的處理路徑從未被執行過,或者它們明顯不在預期之內。與引用return相關的錯誤和問題剛剛開始出現,因為人們開始使用這項功能,並發現了一些不奏效的地方。我認為這在預期之內。我們應該承認這些事實,並且不會採取之前我們撤回預設值型別建構函式功能那樣的行動。

這個功能非常類似。ECMA並沒有針對禁止使用泛型Attribute的內容,在理論上應該可以正常執行,但實際上卻沒有。如果要正常執行,必須更新整個系統中的很多部件:

  1. 存在多個執行時(Mono、CoreRT、整個框架);
  2. IL的一些工具也可能會受到影響(編譯器、基於Cecil或基於CCI2的工具);
  3. 可能需要用於訪問泛型Attribute的API(例如,現有的反射API不允許你訪問泛型Attribute——你必須進行列舉)。

該提案的一個限制是在編譯時必須“關閉”Attribute功能。下面是提案中提供的一個啟用泛型Attribute的例子。

[SomeAttribute\u0026lt;T\u0026gt;]public void DoSomething\u0026lt;T\u0026gt;(T input) { }

因為T不是在編譯時定義的,因此反射機制就不知道這個表示式會返回什麼。

typeof(GenericClass\u0026lt;\u0026gt;).GetMethod(\u0026quot;DoSomething\u0026quot;).GetCustomAttributes()

狀態

目前,泛型Attribute功能列在C# 8路線圖中,狀態為“進行中”。

檢視英文原文https://www.infoq.com/news/2019/01/Generic-Attributes

相關文章