C# 如何处理显式接口事件?
所以我做了一些如下的界面:C# 如何处理显式接口事件?,c#,events,interface,delegates,explicit-interface,C#,Events,Interface,Delegates,Explicit Interface,所以我做了一些如下的界面: public interface IDrawActions : ISimpleDrawable { Action<GameTime> PreDrawAction { get; set; } Action<GameTime> PostDrawAction { get; set; } event EventHandler PreDrawActionChanged; event EventHandler PostDr
public interface IDrawActions : ISimpleDrawable
{
Action<GameTime> PreDrawAction { get; set; }
Action<GameTime> PostDrawAction { get; set; }
event EventHandler PreDrawActionChanged;
event EventHandler PostDrawActionChanged;
}
公共接口IDrawActions:ISimpleDrawable
{
动作预绘制动作{get;set;}
Action PostDrawAction{get;set;}
事件处理程序PreDrawActionChanged;
事件事件处理程序PostDrawActionChanged;
}
任何实现这些接口中的这个(或几个)的类都变得有点混乱,所以我认为使用显式接口实现来隐藏不常见的事件和属性是有意义的。但是,这样做,我得到了一个编译器错误:
事件的显式接口实现必须使用事件访问器语法
通过谷歌搜索,我发现:
这暗示了编写自己的添加和删除访问器的主要原因之一:提供自己的底层数据存储。您可能希望这样做的一个原因是,如果您的类上有很多公开的事件,但在任何时间点,实例上通常只使用少数事件在这种情况下,维护每个事件的委托字段可能会产生大量内存开销。
这究竟如何节省资源?事件的委托调用列表似乎为空,但是如果您使用自己的自定义处理程序,它将如何以及何时被实例化?一切都隐藏起来了 粗体文本指的是内存优化,当您有许多事件或多个对象实例时,这非常有用,所有这些都有许多事件。在C#中创建事件的最基本支持是使用event关键字。此关键字是以下生成代码的语法糖:
- 包含委托的字段。代理形成链接列表。这是列表的标题,并在标题处插入附加内容
- 事件访问器,其中add方法使用delegate字段插入到链表中,remove方法从链表中删除。链表的添加和删除也有语法隐藏,因此您只能看到“+=”和“-=”以添加到代理列表或从代理列表中删除
- 事件标识符。每个唯一类型的事件都有一个唯一标识符。最好使用较小的值,如字节或整数,因为即使在一个巨大的库中,也不太可能有数百万个事件类型
- 代表。委托可以是弱类型的(委托)
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)中,大多数公共属性也被虚拟化,尽管我们将最可能一起使用的属性值捆绑在一起。这使我们能够在所有实例上提供许多属性和事件,而每个实例的这些属性或事件使用的内存为零,除非:
- 对于属性,属性设置为非默认值
- 对于事件,有东西订阅该事件
理想情况下,我们应该拥有不会强迫我们显式优化数据结构的编程工具。精确指定对象在内存中的布局方式是一个负担,由探查器或智能运行时系统更好地处理。在这方面,我们仍然处于石器时代,在我所使用过的每种编程语言中。我了解如何使用显式事件语法,但这不是我的问题;我要求澄清粗体文本,它声称存在“显著的内存开销”