2016-09-13 94 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) 
    { 

    } 
}; 

這只是一個慣例,而不是語言的限制。