Reputation: 2750
I have an abstract class A which has a required function for checking thresholds. When a threshold is violated I want an event raised that says notify me. I've done this sort of thing in Qt many times, but I can't seem to figure out how to transfer this to C#. Here's the structure I've currently got in mind.
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();
}
}
}
Upvotes: 2
Views: 612
Reputation: 49179
Typically the form you want to follow is this:
public event EventHandler<SomeEventArgs> SomeEvent = (s, e) => { };
protected virtual void OnSomeEvent(SomeEventArgs e)
{
SomeEvent(this, e);
}
so in your case you probably want:
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());
}
}
Now a few things - the EventHandler type is some nice syntactic sugar for making an event of a particular type. The lambda expression on the right initializes it to a default handler so you don't have to check it for null before you invoke it.
EventArgs is event-specific information - you have none, but if you did you would subclass EventArgs and put in whatever data your event receivers would need.
The pattern of public event SomeEventName
and protected virtual void OnSomeEvent
pair is prescribed by Microsoft for events in .NET. You don't have to follow this, but it's what .NET programmers want.
Upvotes: 2
Reputation: 11647
There is several issues with this code.
First of all you should use EventHandler built-in delegate for defining events. Second, you can't raise an event outside the class that defines it (that's why you can't use your Notify() from the descendants). Third, you can use Template Method Design Pattern and define contract between your base class and it descendants more clearly and implement one part of the threashold check.
And finally I don't understand at all why you need inheritance hierarchy at all? Maybe you can implement all required logic in one class? But anyway here code that would compile and behave correctly:
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();
}
}
Upvotes: 1
Reputation: 3013
The usual pattern is to provide a protected virtual method in the base class as shown in http://msdn.microsoft.com/en-us/library/vstudio/9aackb16(v=vs.100).aspx. The convention for the name for that method is On[EventName] and takes the event args instance.
Also follow the convention of using EventHandler or EventHandler for the delegate, and provide both the event originator and the corresponding arguments. You can find more about this in http://msdn.microsoft.com/en-us/library/vstudio/ms229011(v=vs.100).aspx. Note that the sample from MSDN does not follow all these conventions.
Upvotes: 0
Reputation: 20757
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);
}
}
}
Then call using:
B b = new B(AlertMe);
b.CheckThreshold();
Upvotes: -1
Reputation: 311
You could define a helper method in base class A
protected void FireNotification()
{
if (Notifier != null)
Notifier();
}
and call this from the overridden CheckTreshold
.
Upvotes: 1