.Net Tips — use [field:NonSerialized] to stop serializing your event handlers

In C#, when you define an event in your class, e.g.:


the event han­dlers will be seri­al­ized along with oth­er prop­er­ties, etc.

This is because under the hood, the com­pil­er trans­lates your event into the fol­low­ing, as can be seen through Jet­Brain’s dot­Peek decom­pil­er:


Since the gen­er­at­ed Even­tHandler is not marked with the [Non­Se­ri­al­ized] attribute there’s no way for the seri­al­iz­er to know that it should be ignored dur­ing the seri­al­iza­tion process.

Solution 1 : implement event explicitly

One solu­tion to this is to imple­ment the event explic­it­ly, so you end up with some­thing along the line of:


Solution 2 : use [field:NonSerialized]

A much bet­ter solu­tion would be to use the [Non­Se­ri­al­ized] attribute on the event, and more specif­i­cal­ly, you want to apply it to the pri­vate Even­tHandler instance that the com­pil­er gen­er­ates for you. Apply­ing the [Non­Se­ri­al­ized] attribute on the event gen­er­ates a com­pil­er error telling you that it’s only valid on field dec­la­ra­tions:



So instead, if you pre­fix the attribute with the ‘field’ key­word every­thing will work as you’d expect:


Closing thoughts…

On a relat­ed note, you may have noticed that my event dec­la­ra­tion assigns an emp­ty han­dler to the event, this is to remove the need for null check­ing before invok­ing an event (which as you can imag­ine requires even more work to make thread-safe). There are oth­er tech­niques (see @BlkRabbitCoder’s post on rais­ing events safe­ly and effi­cient­ly here for more details) to deal with this com­mon prob­lem.

In the case of a class that has to be seri­al­ized, this tech­nique won’t work if the event han­dlers are not seri­al­ized as part of the object, because by the time it’s dese­ri­al­ized the event han­dler will be null.

So instead, cour­tesy of @BlkRabbitCoder, here’re two sim­ple exten­sion meth­ods that encap­su­lates the code nec­es­sary to safe­ly (pre­vents Null­Ref­er­ence­Ex­cep­tion) invoke event han­dlers in a thread-safe man­ner:


Further reading

Here are some more blog posts that go in to more detail about some intri­ca­cies with events in .Net:

Jon Skeet – Del­e­gates and Events

Eric Lip­pert – Events and Races

Safe­ly and Effi­cient­ly rais­ing Events