"Marshal" <(E-Mail Removed)> a écrit dans le message de
news:
9EBD9425-70AD-45D5-8B09-(E-Mail Removed)...
> First... let's deal with Delegates. Comments welcome.
>
> 1) Invoking a NULL delegate is annoying.
> ** (It should just do nothing rather than crash.)
The class that invokes the delegate should always check for null before
calling it.
> 2) It's too easy to accidently attach multiple redundant handlers onto
> delegates.
Not in well written code.
> 3) A delegate might point to handlers on objects that are out of scope or
> been disposed, causing those objects to crash.
> ** (Handlers should be removed automatically when the object that defines
> them leaves scope).
As long as the delegate in class that holds the event has a reference to a
method of another object, then that other object can't be garbage collected
and will remain valid.
> There is sort of a potential for "delegate leak" where objects attach
> handlers indefinitely while the handler functions get called an increasing
> number of times per event...
This is unlikely in well-mannered code.
> Unfortunately, the way to prevent the aforementioned problems is not
> convenient...
>
> So, for protective coding... must we truly declare the laws of proper
> delegate usage as follows? (I hope we can resolve a more convenient way).
>
> ////////////////////////////////////////////////////////
> ///// ALL CLASSES THAT ATTACH TO THE EVENT CHAIN MUST...
>
> // declare member variable of this
> System.EventHandler _hEventHandler;
>
> // during construction of this:
> _hEventHandler = new System.EventHandler(whatever);
>
> // during initialization of this:
> _obj._SomeEvent += _hEventHandler;
>
> // during disposal of this: (all users must call Dispose)
> _obj._SomeEvent -= _hEventHandler;
>
> ////////////////////////////////////////////////////////
public delegate void NotificationHandler(object sender);
public class ReceiverClass
{
public void HandleNotification(object sender)
{
...
}
}
Then the code that creates an instance of this class can also attach its
handler method to the Sender class (see later code)
void MethodToCreateAndAttachToSender
{
SenderClasssc = new SenderClass();
ReceiverClass rc = new ReceiverClass();
sc.Notify += new NotificationHandler(rc.HandleNotification)
}
> ////////////////////////////////////////////////////////
> ///// ALL CLASSES SERVING AN EVENT MUST...
> ////////////////////////////////////////////////////////
> public event System.EventHandler _SomeEvent
> {
> add
> {
> // PREVENTS THE SAME HANDLER FROM BEING ATTACHED MORE THAN ONCE
> Attach(ref _eSomeEvent, value);
> }
> remove
> {
> _eSomeEvent -= value;
> }
> }
>
> private event System.EventHandler _eSomeEvent;
>
> private void _FireSomeEvent()
> {
> Fire(_eSomeEvent, this, whatever);
> }
>
> public static void Fire(System.EventHandler h, object sender,
> System.EventArgs args)
> {
> // PROTECTS FROM EVENT INVOKED WHEN NULL
> if(h!=null) h(sender, args);
> }
>
> public static void Attach(ref System.EventHandler h1, System.EventHandler
h2)
> {
> // PROTECTS FROM SAME HANDLER BEING ADDED MULTIPLE TIMES
> if(h2==null) return;
> if(h1!=null)
> {
> System.Delegate[] ar = h1.GetInvocationList();
> foreach(System.Delegate dg in ar) if(dg == h2) return;
> }
> // (this is okay when h1 is null)
> h1 += h2;
> }
This is overkill and not necessary; if you follow the guidelines for setting
up a multicast delegate as an event, then all you need to do is the
following :
public delegate void NotificationHandler(object sender);
public class SenderClass
{
private void OnNotify(object someObject)
{
if (Notify != null)
Notify(someObject);
}
public event NotificationHandler Notify;
public void SomeMethodThatNeedsToInvokeEvent
{
// make changes
OnNotify(this);
}
Why do you think you need all that extra code ??
Joanna
--
Joanna Carter
Consultant Software Engineer