粗體文本指的是內存優化,當您有很多事件或許多對象實例,並且都有很多事件時,該優化非常有用。在C#中創建事件的最基本支持是使用事件關鍵字。此關鍵字爲以下生成代碼的語法糖:
- 包含委託的字段。代表形成鏈接列表。這是列表的頭部,並且在頭部插入添加。
- 事件訪問器,其中add方法使用委託字段插入鏈接列表,並且remove方法從鏈接列表中刪除。鏈接列表的添加和刪除也有隱藏它的語法糖,所以您只能看到「+ =」和「 - =」添加到委託列表或從委託列表中刪除。
在這個意義上,事件關鍵字產生類似於從C#自動實現的屬性生成的代碼的代碼。
開銷是爲每個事件維護一個單獨的字段。這不是必需的,就像沒有必要爲支持每個類暴露的屬性的數據維護單獨的字段一樣。我們可以虛擬化事件字段和屬性字段。
我們如何明確消除事件的開銷?我們在像VG.net這樣的庫中使用這種方法,並且Microsoft在其代碼中使用了類似的方法:將一組事件保存在單個字段中。在大多數情況下,很少有事件擁有許多事件訂閱者。最簡單的集合是類實例的鏈表。集合中的每個元素由包含以下屬性的類實例組成:
- 事件標識符。每種獨特類型的事件都有一個唯一標識符。最好使用一些小的東西,比如字節或整數,因爲即使在一個巨大的庫中,你也不可能擁有數以百萬計的事件類型。
- 代表。代表可以是弱類型的(Delegate)。
當您需要爲訂戶添加事件處理程序時,請使用唯一事件類型標識符查找集合中的委託。您第一次查找時,收藏品不會包含它。在添加事件處理程序的情況下,您將爲您的集合添加一個元素,並在該元素中使用Delegate.Combine將其添加到存儲在那裏的委託。要刪除處理程序,請使用Delegate.Remove。
這裏是真正的代碼示例中VG.net:
private static readonly int MouseDownEvent = EventsProperty.CreateEventKey();
public event ElementMouseEventHandler MouseDown
{
add { AddHandler(MouseDownEvent, value); }
remove { RemoveHandler(MouseDownEvent, value); }
}
public virtual void OnMouseDown(ElementMouseEventArgs args)
{
ElementMouseEventHandler handler =
FindHandler(MouseDownEvent) as ElementMouseEventHandler;
if (handler != null)
handler(this, args);
}
internal void AddHandler(int key, Delegate value)
{
EventsProperty p = (EventsProperty)GetOrInsertProperty(EventsProperty.Key);
p.AddHandler(key, value);
}
internal void RemoveHandler(int key, Delegate value)
{
EventsProperty p = (EventsProperty)GetProperty(EventsProperty.Key);
if (p == null)
return;
p.RemoveHandler(key, value);
}
internal Delegate FindHandler(int key)
{
EventsProperty p = (EventsProperty)GetProperty(EventsProperty.Key);
if (p == null)
return null;
return p[key];
}
我們虛擬化,不僅事件,但性質也是如此。對於VG.net,所有事件都包含在一個虛擬屬性(EventProperty)中,並且大多數公共屬性也是虛擬化的,儘管我們將最有可能一起使用的屬性值捆綁在一起。這使我們能夠在所有情況下提供了許多屬性和事件,同時有通過將這些屬性或者每個實例事件使用零內存,除非:
- 有關屬性,該屬性設置爲一個非默認值。
- 對於事件,某些事件訂閱事件。
即使在內存中有數百萬個圖形對象,即使運行在低端硬件上,這些優化類型也會使VG.net高效。
理想情況下,我們應該有編程工具,不要求我們明確優化數據結構。確切地指定對象在內存中的佈局方式是一個由Profiler或智能運行系統更好處理的負擔。在這方面,我們仍然處於石器時代,在我曾經工作過的每種編程語言中。
http://stackoverflow.com/questions/2268065/c-sharp-language-design-explicit-interface-implementation-事件 – mybirthname 2014-10-17 15:27:48
我明白如何使用顯式事件語法,但這不是我的問題;我要求澄清粗體文本,聲稱存在「重大的內存開銷」 – 2014-10-17 15:33:45