2016-09-13 97 views
2

是否可以将Enum元素作为事件参数传递?将枚举元素传递为事件参数C#

比方说,我有..

public class Letters 
{ 
    public delegate void StateChangedEventHandler(object sender, EventArgs e); 
    public event StateChangedEventHandler StateChanged; 

    public AbcState state = AbcState.Aaa;  
    public AbcState State 
    { 
     get{return this.state;} 
     set 
     { 
      this.state = value; 
      this.OnStateChanged(); 
     } 
    } 

    public enum AbcState 
    { 
     Aaa, 
     Bbb, 
     Ccc 
    } 

    protected virtual void OnStateChanged() 
    { 
     StateChanged?.Invoke(this, State); 
    } 

看我怎么我试图枚举的元素作为传递事件参数? 现在,我通常会创建一个类并扩展EventArgs,然后我将能够传递这个类本身。 我知道我可以在这里做同样的事情,创建一个扩展EventArgs的不同类,然后在类中创建枚举,字段和属性。然后将后者的一个实例放入我的类“Letters”(在上面的代码中使用)。

但是,是不是疯了?一定有更好的方法。请告诉我有一个更简单的方法。

顺便说一下,我不知道上面的代码是否会编译我只是直接在编辑器中编写它,因为我现在不在我的开发计算机上。

+0

代码的复杂性是主观的。但是,为了标准化应用程序之间的对话,应遵守编码标准。如果您的应用程序不会被任何其他库使用,请停止阅读此处。标准事件委托签名是有原因的 - 即'EventHandlerMethod(object sender,EventArgs e)'。再一次,这是主观的,但是如果有可能这个图书馆会被另一个图书馆和另一个图书馆生成的事件被另一个图书馆使用,那么偏离这种做法是不好的做法。请参阅https://msdn.microsoft.com/en-us/library/ms182133.aspx – IAbstract

回答

2

如果你想事件的参数是枚举,那么肯定,只是指定作为签名声明事件时:

public class Letters 
{ 
    public event Action<AbcState> StateChanged; 

    private AbcState state = AbcState.Aaa;  
    public AbcState State 
    { 
     get{return this.state;} 
     set 
     { 
      this.state = value; 
      this.OnStateChanged(); 
     } 
    } 

    public enum AbcState 
    { 
     Aaa, 
     Bbb, 
     Ccc 
    } 

    protected virtual void OnStateChanged() 
    { 
     StateChanged?.Invoke(State); 
    } 
} 
+0

改为使用'EventHandler '。至少事件处理程序使用'...(对象发件人,e)'事件代表的签名。更好的是,使用'AbcStateEventArgs'类:'EventHandler '保持标准签名更好。代码分析将呕吐所有不遵循标准实现的事件处理程序。 – IAbstract

+1

@IAbstract全部添加完成任何内容。它使代码复杂化,并没有提供任何价值。另外,OP还特意表示,他知道如何做到这一点,他问如何避免必须这样做,而且我承诺。 – Servy

+0

代码的“复杂性”是主观的。虽然作为一个惯例,如果图书馆被其他方使用,也会有假设。 – IAbstract

2

不,这不是疯了。遵循约定并不疯狂,即使它们有时看起来有点笨重,因为那些维护你的代码的人(包括你,在你忘记写这些东西之后)会发现尽可能少的惊喜。

你确实有使用EventHandler<T>的选项,但是:

public event EventHandler<AbcState> StateChanged; 

protected void OnStateChanged(AbcState state) 
{ 
    StateChanged?.Invoke(this, state); 
} 

顺便说一句,你不必声明一个新的冗余委托类型来声明一个事件。这是与您的原始声明:

public event EventHandler StateChanged; 

的最好的事情可能会写这样的:

public class ValueEventArgs<T> : EventArgs 
{ 
    public ValueEventArgs(T value) 
    { 
     Value = value; 
    } 

    public T Value { get; protected set; } 
} 

并使用它像这样:

public event EventHandler<ValueEventArgs<AbcState>> StateChanged; 

protected void OnStateChanged(AbcState state) 
{ 
    StateChanged?.Invoke(this, new ValueEventArgs<AbcState>(state)); 
} 

你也可以写一个ValueChangedEventArgs<T>与旧的和新的价值属性等等,但EventHandler<AbcState>是你最快的类型安全的方式做你想做的。

最后,你可以使用Action<T>作为event委托,但这是一个坏主意。人们看到Action<T>,他们不认为它是一个event。当有人试图阅读你的代码时,你添加的唯一东西就是混乱。除非有一些明确的优势(并且这里没有),否则不要编写代码,乍一看,它看起来不是这样。

+0

使用'Action'作为事件的委托并不会阻止多个订阅者。它*是一个事件,即使你使用'Action'作为代表。 – Servy

+0

@Servy我错过了'event'关键字。将更新。 –

+0

@Servy尽管如此,编写代码看起来并不是一个好主意。没有人期待一个“行动”是一个事件。任何你不得不停下来说“WTF?”的地方对可维护性来说是一个坏主意。 –

2

没有什么能阻止你从没有以下事件处理约定:

public enum Test { X } 

public class A 
{ 
    public event Action<Test> StuffDone;  
} 

你就可以做到这一点:

A a = new A(); 
a.StuffDone += test => 
{ 
    if(test == Test.X) 
    { 

    } 
}; 

这只是一个惯例,而不是语言的限制。