我试图更多地使用界面,并且经常发现自己将事件放入界面中。感觉很奇怪,因为我让实现者知道何时在其实现中引发这些事件。
例如,我有一个ILevellable接口,该接口仅声明对象应具有xp,一个级别和一个最大级别,以及一些修改这些值的方法。引用ILevellable的类可能想知道何时升级,因此我为OnLevelUp添加了一个Action ...,但是该实现可能未将其放在正确的位置。
public interface ILevellable
{
int Level { get; }
int MaxLevel { get; }
int XP { get; }
event Action<bool> OnXPChanged;
event Action<ILevellable> OnLevelUp;
event Action OnMaxLevelReached;
void LevelUp(int newLevel);
}
我应该相信实现此接口的用户会知道在哪里实现吗?我会假设不是。尤其是因为某些事件可能带有参数,用户又可能不知道它应该代表什么。
我感谢任何指导!我是这种工作的新手。
谢谢!
答案 0 :(得分:1)
可以在界面中定义事件。但是,将“发件人”和“事件参数”都传递到事件中符合惯例。 TypedEventHandler是一种简单的方法。例如:
using Windows.Foundation;
public struct LevellableChange {
public LevellableChange( int dl, int dxp)
{
this.ChangeInLevel = dl;
this.ChangeInXP = dxp;
}
int ChangeInLevel { get; }
int ChangeInXP {get;}
}
public interface ILevellable
{
int Level { get; }
int MaxLevel { get; }
int XP { get; }
event TypedEventHandler< ILevellable, LevellableChange> Changed;
}
然后,实现它们的标准方法如下:
public class Levellable: ILevellable
{
public event TypedEventHandler<ILevellable, LevellableChange> Changed;
public int Level {
get {
return this._level;
}
private set {
if (value != this._level) {
int oldLevel = this._level;
this._level = value;
this.Changed?.Invoke(this, new LevellableChange(value - oldLevel, 0));
}
}
}
private int _level;
// similar for XP.
}
另一个评论是,有一个实现INotifyPropertyChanged的类,然后养成从其派生的习惯很有用。加上Visual Studio中的代码片段,这使事情变得容易得多。确实,对于上面的示例,INotifyPropertyChanged不够,因为它没有将更改赋予先前的值。
答案 1 :(得分:0)
首先,您的接口定义中没有委托类型,但事件。查看乔恩·斯凯特(Jon Skeet)的this answer,以了解委托和事件之间的区别。说完接口中有事件是完全可以的,即使.Net也可以这样做,再考虑一下著名的INotifyPropertyChanged接口。它只是定义了一个事件...
第二:
我应该相信实现此接口的用户会知道在哪里实现吗?
定义接口时,您实际上并不关心实现者,而不是消费者,因此,对于看到您的合同定义的消费者来说,知道他/她可以订阅名为{{1 }}。假设我确实在使用您的界面,我不知道您触发OnLevelUp
事件的方式或时间,我也不在乎,因为您为该事件指定了一个非常语义化和有意义的名称,因此我可以非常确定在增加OnLevelUp
的Level属性时会触发该事件。