Using my cusom EventArgs such as :
public event EventHandler<MyEventArgs> SampleEvent;
from msdn e.g :
public class HasEvent
{
// Declare an event of delegate type EventHandler of
// MyEventArgs.
public event EventHandler<MyEventArgs> SampleEvent;
public void DemoEvent(string val)
{
// Copy to a temporary variable to be thread-safe.
EventHandler<MyEventArgs> temp = SampleEvent;
if (temp != null)
temp(this, new MyEventArgs(val));
}
}
I have 2 questions:
1)
looking at the marked code :

I don’t see a reason why it should be copied to another param ( regarding threads)
since we have the event keyowrd , no one can touch its invocation list ( no outsider code to the class I mean)
2) If I’m not mistaken, the DemoEvent function should be virtual, so it can be overridden in sub classes… (I’m sure I’ve seen it somewhere)
the strange thing is that resharper also won’t add virtual :
so if I have this code:

it suggests me :

and when I press it :

so again my 2 questions :
1) What is the scenario which this line EventHandler<MyEventArgs> temp = SampleEvent; will solve , regarding thread safty?
2) Shouldn’t the function be virtual? ( I’m sure I’ve seen this pattern with virtual)
Imagine you do this:
If another thread will detach the event handler after the if but before the invocation then you’ll try to call a
nulldelegate (and you’ll get an exception).Yes, if the class is not
sealedthen you should mark that functionvirtual(it’s not mandatory but it’s a well accepted pattern).EDIT
Time Thread 1 Thread 2 1 obj.SampleEvent += MyHandler; 2 if (SampleEvent != null) 3 { obj.SampleEvent -= MyHandler; 4 SampleEvent(this, new MyEventArgs()); 5 }In this case at time 4 you’ll call a
nulldelegate and it’ll throw aNullReferenceException. Now look this code:Time Thread 1 Thread 2 1 obj.SampleEvent += MyHandler; 2 var sampleEvent = SampleEvent; 3 if (sampleEvent != null) 4 { obj.SampleEvent -= MyHandler; 5 sampleEvent(this, new MyEventArgs()); 6 }Now at time 5 you call
sampleEventand it holds the old content ofSampleEvent, in this case it won’t throw any exception (but it’ll callMyHandlereven if it has been removed by the second thread).