在显式实现接口时,是否有更好的方法在C#中编写这个重复的事件声明代码?

时间:2010-05-06 18:20:19

标签: c# refactoring events boilerplate

我有很多代码,如下所示,我明确地实现了接口所需的一些事件。

public class IMicrowaveNotifier {
  event EventHandler<EventArgs> DoorClosed;
  event EventHandler<EventArgs> LightbulbOn;
  // ...
}

public class Microwave : IMicrowaveNotifier {
  private EventHandler<EventArgs> _doorClosed;
  event EventHandler<EventArgs> IMicrowaveNotifier.DoorClosed {
    add { lock (this) _doorClosed += value; }
    remove { lock (this) _doorClosed -= value; }
  }

  private EventHandler<EventArgs> _lightbulbOn;
  event EventHandler<EventArgs> IMicrowaveNotifier.LightbulbOn {
    add { lock (this) _lightbulbOn += value; }
    remove { lock (this) _lightbulbOn -= value; }
  }

  // ...
}

你可以看到很多这是样板文件。在Ruby中,我可以做到这样的事情:

class Microwave
  has_events :door_closed, :lightbulb_on, ...
end

在C#中删除此样板是否有类似的更短方法?


更新:我从我的示例中留下了一个非常重要的部分:即,实现的事件是接口的一部分,我想明确地实现它。很抱歉没有提到这个!

4 个答案:

答案 0 :(得分:10)

试试这个:

public class Microwave {
    public event EventHandler<EventArgs> DoorClosed;
    public event EventHandler<EventArgs> LightbulbOn;
}

此代码利用了C#的field-like event syntax

  

在编译类似字段的事件时,   编译器自动创建存储   持有代表,并创造   添加或的事件的访问器   删除委托的事件处理程序   字段。

在C#1,2和3中,此代码将编译为您上面的内容。在C#4中,您将获得与doesn't use explicit locks功能相同的代码。无论哪种方式,您都可以使用此快捷方式而无需更改此类消费者。

更新:不幸的是,C#编译器不允许您使用类似字段的事件来实现显式接口。如果您尝试,将收到此编译错误:

  

事件的显式接口实现必须使用事件访问器语法

更新:显式接口实现需要使用事件访问器语法,这太糟糕了。如果C#添加了创建自动实现的类似字段的事件的能力,那将会很酷:

event EventHandler<EventArgs> IAppliance.DoorClosed { add; remove; }

但是这种语法已经比现有的类字段事件语法更加冗长,并且只适用于显式实现接口成员的情况。我认为最好的事情是编译器只允许我们这样做:

event EventHandler<EventArgs> IAppliance.DoorClosed;

答案 1 :(得分:0)

我不确定Lock做什么,因为我是新手,但你可以将所有控件或任何调用这些事件的内容连接到一个事件。在那种情况下,只需执行if语句来检查发送者是谁。

我觉得它看起来会更整洁,但我仍然需要做一些工作。

答案 2 :(得分:0)

为其编写代码段并使用快捷方式。就像使用if,for,foreach {tab} {tab}一样。

答案 3 :(得分:0)

gbogumil建议的代码段将节省一些时间。或者,如果有一个特定的接口,你发现自己经常需要这个,你是否有可能创建一个抽象的基类?