3

I have often seen code examples of delegate invocation being done as follows:

`

    public delegate void DelegateThreadActivity<T, U> (T sender, U e);

    public event DelegateThreadActivity<Thread, System.EventArgs> OnStart = null;
    public event DelegateThreadActivity<Thread, System.EventArgs> OnStop = null;

    // Helper method for invocation.
    public void RaiseOnStart ()
    {
        DelegateThreadActivity<Thread, System.EventArgs> instance = null;

        try
        {
            instance = this.OnStart;
            // OR
            instance = (DelegateThreadActivity) (object) this.OnStart;

            if (instance != null)
            {
                instance(this, System.EventArgs.Empty);
            }
        }
        catch
        {
        }
    }

`

Why use the [instance] object at all? At first I thought it was corporate convention but have seen seasoned developers do this as well. What is the benefit?

Raheel Khan
  • 14,205
  • 13
  • 80
  • 168

1 Answers1

6

This is done because of thread safety, and prevention of exception raising in the case the delegate turns null.

Consider this code:

if (this.OnStart != null)
{
  this.OnStart(this, System.EventArgs.Empty);
}

Between the execution of the if and the execution of this.OnStart, the OnStart delegate could have been manipulated (possibly changed to null, which would result in an exception).

In the form you provided in your question, a copy of the delegate is made and used when executing. Any change in the original delegate will not be reflected in the copy, which will prevent an exception from coming up. There is a disadvantage with this though: As any changes in the meantime will not be reflected in the copy, which also includes any non-null state, will result in either calling delegates already removed or not calling delegates recently added to it.

Femaref
  • 60,705
  • 7
  • 138
  • 176
  • Thanks. I hadn't thought about thread safety. Probably since it is not intuitive to consider as you mention the natural drawback to this approach. Also, I did not know that delegates behaved this way. I would think that assigning `instance = this.OnStart` would act like reference types do. Could you point me to a good resource to learn more about this? – Raheel Khan May 06 '12 at 02:15
  • And also, why the boxing type convention in the second example? Is that to enforce non-reference-type-like behavior? – Raheel Khan May 06 '12 at 02:17
  • 1
    @RaheelKhan, see [this article](http://blogs.msdn.com/b/ericlippert/archive/2009/04/29/events-and-races.aspx) for details – Thomas Levesque May 06 '12 at 02:17
  • Immutable was the key word there. Cheers. – Raheel Khan May 06 '12 at 02:34
  • @RaheelKhan this is not boxing; it is casting. – phoog May 06 '12 at 05:53
  • @phoog: Yes I know and used the term 'boxing-like' to emphasize on the fact that it seemed pointless to cast up the hierarchy and back again. And as it appears to be the case, casting like this does not seem to have relevance to the reason this approach is used. In other words, the second example is pointless I'm guessing. – Raheel Khan May 06 '12 at 06:20
  • @RaheelKhan some versions of the jit compiler will optimize away the local variable, which leaves you with exactly the same problem you started with. The casting is probably an attempt to prevent the optimization. Whether it is successful, I have no idea. – phoog May 06 '12 at 06:34
  • @phoog: I see your point. Although since I have seen MVPs using this approach, I am guessing the VS compiler does not treat delegates that way. – Raheel Khan May 06 '12 at 07:15