2012-11-30 66 views
1

我有一個抽象類A,它具有檢查閾值所需的功能。當違反閾值時,我希望提出一個事件通知我。我多次在Qt中做過這類事情,但我似乎無法弄清楚如何將它傳遞給C#。這是我目前想到的結構。籌集事件的模式

namespace N 
{ 
    abstract class A 
    { 
    public delegate void Notify(); 
    public event Notify Notifier; 
    public abstract void CheckThreshold(); 
    } 

    class B : A 
    { 
    public override void CheckThreshold() 
    { 
     Notifier(); 
    } 
    } 

    class N 
    { 
    public AlertMe() 
    { 
    } 
    public static Main() 
    { 
     var b = new B(); 
     b.Notifier += new A.Notify(AlertMe); 

     b.CheckThreshold(); 
    } 
    } 
} 
+0

我已編輯您的標題。請參閱:「[應該在其標題中包含」標籤「](http://meta.stackexchange.com/questions/19190/)」,其中的共識是「不,他們不應該」。 –

回答

1

通常要遵循的形式是這樣的:

public event EventHandler<SomeEventArgs> SomeEvent = (s, e) => { }; 

protected virtual void OnSomeEvent(SomeEventArgs e) 
{ 
    SomeEvent(this, e); 
} 

所以你的情況,你可能想:

abstract class A { 

    public event EventHandler<EventArgs> ThresholdExceeded = (s, e) => { }; 

    protected virtual void OnThresholdExceeded(EventArgs e) 
    { 
     ThresholdExceeded(e); 
    } 

    public abstract void CheckThreshold(); 
} 

class B : A { 
    public override void CheckThreshold() 
    { 
     if (/* your condition */) OnThresholdExceeded(new EventArgs()); 
    } 
} 

現在的幾件事情 - 在事件處理程序類型是一些不錯的語法糖製作特定類型的活動。右側的lambda表達式將其初始化爲默認處理程序,因此在調用它之前不必檢查它是否爲null。

EventArgs是特定於事件的信息 - 你沒有,但是如果你做了,你可以繼承EventArgs的子類並且放入事件接收器需要的任何數據。

public event SomeEventNameprotected virtual void OnSomeEvent對的模式由Microsoft爲.NET中的事件規定。你不需要,但它是.NET程序員想要的。

+0

你可能指的是規定。它真的改變了意義:) – fsimonazzi

1

您可以定義在基類

protected void FireNotification() 
{ 
    if (Notifier != null) 
     Notifier(); 
} 

一個輔助方法,並從覆蓋CheckTreshold調用它。

-1
public abstract class A 
{ 
    public EventHandler<EventArgs> OnThresholdViolated; 

    public abstract void CheckThreshold(); 
} 

public class B : A 
{ 
    public B(EventHandler<EventArgs> alertMe) { 
     OnThresholdViolated += alertMe; 
    } 

    public override void CheckThreshold() 
    { 
     if (null != OnThresholdViolated) 
     { 
      OnThresholdViolated(this, EventArgs.Empty); 
     } 
    } 
} 

然後調用使用:

 B b = new B(AlertMe); 

     b.CheckThreshold(); 
+0

事件是私人領域,你不能使用它們從子類作爲代表。此外,空檢查應該是一個局部變量,以避免競爭條件。 – fsimonazzi

+0

@fsimonazzi:你想檢查第一條語句嗎?我在VS中編寫並測試了這段代碼,它的工作非常完美。不過,你說的第二點是正確的。 –

+0

你是正確的代碼工作。沒有注意到你沒有使用一個事件,而是一個普通的代表。但那些不是事件!而且由於它是公開的,任何人都可以改變它。 – fsimonazzi

0

通常的圖案是提供在基類受保護的虛方法,如圖http://msdn.microsoft.com/en-us/library/vstudio/9aackb16(v=vs.100).aspx。該方法的名稱的約定是On [EventName]並使用事件參數實例。

也遵循爲委託使用EventHandler或EventHandler的約定,並提供事件創建者和相應的參數。您可以在http://msdn.microsoft.com/en-us/library/vstudio/ms229011(v=vs.100).aspx中找到更多關於此的信息。請注意,來自MSDN的示例並不遵循所有這些慣例。

1

該代碼有幾個問題。

首先,您應該使用EventHandler內置委託來定義事件。其次,你不能在定義它的類之外引發一個事件(這就是爲什麼你不能從後代使用你的Notify())。第三,您可以使用Template Method Design Pattern並更清楚地定義您的基類與其後代之間的契約,並執行threashold檢查的一部分。

最後我根本不明白爲什麼你需要繼承層次結構?也許你可以在一個類中實現所有必需的邏輯?但無論如何這裏代碼將編譯和行爲正確:

abstract class A 
    { 
    // Avoid defining custom delegate at all because there is a lot of 
    // build-in events for every case, like EventHandler<T>, 
    // Func<T>, Action<T> etc 
    // public delegate void Notify(); 
    public event EventHandler ThreasholdViolated; 

    protected void OnThreasholdViolated() 
    { 
     var handler = ThreasholdViolated; 
     if (handler != null) 
     handler(this, EventArgs.Empty); 
    } 

    public abstract void CheckThreshold(); 
    } 

    class B : A 
    { 
    public override void CheckThreshold() 
    { 
     OnThreasholdViolated(); 
    } 
    }