1. 事件沒有通用性絕大多數對象沒有事件的設計需求,不會實現事件。2. 事件沒有抽象性事件並非對象的基本元素,並不反映對象的關鍵抽象。欄位反映對象狀態,方法反映對象行為,事件反映什嗎?一個觀察-通知的關係結構嗎?3. C#事件的實現效能比較低下. a.C#事件的背後是一個委託鏈表(單鏈表),單鏈表的遍曆調用效能遠低於數組鏈表(List<T>) b.C#事件預設實現會產生一個委託欄位執行個體,支援不用的委託欄位執行個體是一個效能負擔(參見WPF/SL裡面的路由事件的改造設計)4. 事件沒有必要性——這一條是C#事件最大的問題事件只是觀察者設計模式的變體。其完全可以用介面來實現。將所謂常用的設計模式變成語言構造的一部分,是C#設計思想裡面又一個的嚴重錯誤(第一個嚴重錯誤是為了所謂的功能,而不管不問效能成本,在前文《C#會重蹈覆轍嗎?系列之2:反射及中繼資料的效能問題》中對此有詳述)。C#中類似的例子還有:使用foreach和yield支援迭代器模式,使用using支援Dispose設計模式。如果可以在C#語言中內建Observer模式,內建Iterator模式, 內建Dispose模式,那麼要不要也把Adapter模式變成C#語言的一部分?要不要把Proxy模式也變成C#語言的一部分?要不要把Bridge模式也變成C#語言的一部分?.....幾百種模式是否都要變成C#語言的一部分???...另外,在語言中內建設計模式,會使得該模式失去實現上的靈活性、或者損傷效能(比如C#事件就限定了觀察者模式必須使用委託來完成事件調用,使用委託鏈表來表達觀察者的對象集合,這種限制使得設計模式失去了其實現上的靈活性)使用程式庫來支援設計模式是程式設計語言的正道,將模式整合為語言的一部分來耍cool,最後的結果是這個語言越來越臃腫,越來越龐大。希望C#設計師們在這條道路上止步。
今天來談談C#語言中事件的設計問題——這是除了效能問題之外,C#語言設計哲學中另外一個嚴重的問題——不必要的臃腫。C#事件總共存在以下4類問題:
1. C#事件沒有抽象性
事件並非對象的基本元素,並不反映對象的關鍵抽象。欄位反映對象狀態,方法反映對象行為,事件反映什嗎?一個觀察-通知的關係結構嗎?
2. C#事件沒有通用性
絕大多數對象沒有事件的設計需求,不會實現事件。
3. C#事件的實現效能比較低下
a.C#事件的背後是一個委託鏈表(單鏈表),單鏈表的遍曆調用效能遠低於數組鏈表(List<T>)
b.C#事件預設實現會產生一個委託欄位執行個體,支援不用的委託欄位執行個體是一個效能負擔(參見WPF/SL裡面的路由事件的改造設計)
4. C#事件沒有必要性——這一條是C#事件最大的問題,也是本文的重點
事件只是觀察者設計模式的變體。其完全可以用介面來實現。
將所謂常用的設計模式變成語言構造的一部分,是C#設計思想裡面又一個的嚴重錯誤(第一個嚴重錯誤是為了所謂的功能,而不管不問效能成本,在前文《C#會重蹈覆轍嗎?系列之2:反射及中繼資料的效能問題》中對此有詳述)。
C#中類似的例子還有:使用foreach和yield支援迭代器模式,使用using支援Dispose設計模式——我就在這裡一併批評了,不再另外撰文了。
如果可以在C#語言中內建Observer模式,內建Iterator模式, 內建Dispose模式,那麼要不要把Adapter模式也變成C#語言的一部分?要不要把Proxy模式也變成C#語言的一部分?Bridge呢?Composite呢?Strategy呢?.....幾百種模式是否都要變成C#語言的一部分???...
另外,在語言中內建設計模式,會使得該模式失去實現上的靈活性、或者損傷效能(比如C#事件就限定了觀察者模式必須使用委託來完成事件調用,使用委託鏈表來表達觀察者的對象集合,這種限制使得設計模式失去了其實現上的靈活性)
使用程式庫來支援設計模式是程式設計語言的正道,將模式整合為語言的一部分來耍cool,最後的結果是這個語言越來越臃腫,越來越龐大。希望C#設計師們在這條道路上止步。