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

发布于 2024-09-01 07:33:53 字数 975 浏览 8 评论 0原文

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

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# 中的样板文件?


更新:我在示例中遗漏了一个非常重要的部分:即,实现的事件是接口的一部分,我想显式地实现它。抱歉没有早点提到这一点!

I have a lot of code like the following, where I explicitly implement some events required by an interface.

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; }
  }

  // ...
}

You can see that much of this is boilerplate. In Ruby I'd be able to do something like this:

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

Is there a similar shorter way of removing this boilerplate in C#?


Update: I left a very important part out of my example: namely, the events getting implemented are part of an interface, and I want to implement it explicitly. Sorry for not mentioning this earlier!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

盗梦空间 2024-09-08 07:33:53

试试这个:

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;

Try this:

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

This code leverages C#'s field-like event syntax:

When compiling a field-like event, the
compiler automatically creates storage
to hold the delegate, and creates
accessors for the event that add or
remove event handlers to the delegate
field.

In C# 1, 2, and 3 this code will compile down to just what you have above. In C# 4 you will get functionally equivalent code that doesn't use explicit locks. Either way you can use this shortcut without changing the consumers of this type.

Update: Unfortunately, the C# compiler does not allow you to use field-like events for explicit interface implementation. If you try you will get this compilation error:

An explicit interface implementation of an event must use event accessor syntax

Update: It's too bad that an explicit interface implementation requires the use of event accessor syntax. It would be kind of cool if C# added the ability to create automatically implemented field-like events like this:

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

But this syntax is already wordier than the existing field-like event syntax and would only be applicable in cases where an interface member was being explicitly implemented. The best thing I think would be if the compiler would simply allow us to do this:

event EventHandler<EventArgs> IAppliance.DoorClosed;
╭ゆ眷念 2024-09-08 07:33:53

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

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

I am not sure what Lock does as I am kind of new, but you can connect all of the controls or whatever is calling those events to only one event. In that event just do a if statement to check who is sending it.

It would look much neater I would think, but still require a some amount of work I guess.

定格我的天空 2024-09-08 07:33:53

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

Write a code snippet for it and use a shortcut. Just like when you use if, for, foreach{tab}{tab}.

兔姬 2024-09-08 07:33:53

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

Code snippets as suggested by gbogumil will save some time. Alternately, if there's a specific interface you find yourself implementing regularly that requires this, is it possible for you to create an abstract base class?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文