在显式实现接口时,是否有更好的方法在 C# 中编写这种重复的事件声明代码?
我有很多如下代码,其中我显式实现了接口所需的一些事件。
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
试试这个:
此代码利用 C# 的类似字段的事件语法:
在 C# 1、2 和 3 中,此代码将编译为上面的内容。在 C# 4 中,您将获得功能等效的代码 不使用显式锁定。无论哪种方式,您都可以使用此快捷方式,而无需更改此类型的使用者。
更新:遗憾的是,C# 编译器不允许您使用类似字段的事件来实现显式接口。如果你尝试,你会得到这个编译错误:
更新: 显式接口实现需要使用事件访问器语法,这太糟糕了。如果 C# 添加了创建自动实现的类字段事件的功能,就像这样,那就太酷了:
但是这种语法已经比现有的类字段事件语法更加冗长,并且仅适用于显式接口成员的情况实施的。我认为最好的事情是编译器允许我们这样做:
Try this:
This code leverages C#'s field-like event syntax:
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:
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:
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:
我不确定
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 aif
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.
为其编写一个代码片段并使用快捷方式。就像使用 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}.
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?