粗体文本指的是内存优化,当您有很多事件或许多对象实例,并且都有很多事件时,该优化非常有用。在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