2

我有很多类似下面的代码,其中我显式地实现了接口所需的一些事件。

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

4 回答 4

10

尝试这个:

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

此代码利用 C# 的类字段事件语法

编译类字段事件时,编译器会自动创建存储来保存委托,并为事件创建访问器,以将事件处理程序添加或删除到委托字段。

在 C# 1、2 和 3 中,此代码将编译为您上面的代码。在 C# 4 中,您将获得不使用显式锁的功能等效代码。无论哪种方式,您都可以使用此快捷方式而无需更改此类型的使用者。

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

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

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

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

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

event EventHandler<EventArgs> IAppliance.DoorClosed;
于 2010-05-06T18:22:33.217 回答
0

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

于 2010-05-06T18:44:44.497 回答
0

我不确定Lock我是个新手,但您可以将所有控件或调用这些事件的任何东西连接到一个事件。在那种情况下,只需做一个if声明来检查谁在发送它。

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

于 2010-05-06T18:28:45.243 回答
0

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

于 2010-05-06T18:36:43.840 回答