Best Practices for .NET events

Event definition

To ease event management in .NET, Microsoft strongly recommends to define events according the following pattern:

    event EventHandler<TEventArgs> Event;

 

All you have to define is an own TEventsArgs class that is inherited from EventArgs. This is done to ease the maintainability of events, it is likely that in future, the class gets enhanced. If you would not follow the pattern, each time you change the event, you would have a breaking API change. Reason: You have to add additional parameters to your delegate. That breaks existing code. This pattern prevents that breaking API change.

The TEventArgs class should be named after the event. The event itself should not contain "Event" within its class name.

So, a concrete example would be:

    event EventHandler<ChangedEventArgs> Changed;

 

Event raising

In .NET, an event is some synatic sugar to a list of delegates. In case no one is registered to an event, that event simply returns null. This is by design and will not be changed by Microsoft.

So, before you can raise an event, you have to check for null. But caution, each time you access the event, you will get a new list of delegates. This is by design and will not be changed, too. Hence, the following code contains a race condition that is hard-to-debug:

    if (Changed != null)
    {
        Changed(sender, new ChangedEventArgs(someData));
    }

 

To avoid that situation, you have to store the delegates into a local variable and invoke that.

    var handlers = Changed;
    if (handlers != null)
    {
        handlers(sender, new ChangedEventArgs(someData));
    }

 

Hence, each time you try to raise an event, you have to keep that in mind. This leads to a lot of duplicated code and is error-prone.

To avoid such situation, we can define and use an extension method. That method ensures that the race-condition is gone and, as we can use it everywhere, no mistake can be done.
The extension method (I've put it into our "Common" project) will look like:

    public static void RaiseWith<TEventArgs>(this EventHandler<TEventArgs> handlers, object sender, TEventArgs e) where TEventArgs : EventArgs
    
{
        
if (handlers != null)
        {
            
handlers(sender, e);
        
}
    } 

 

Now, we can raise an event easily the following way:

    Changed.RaiseWith(sender, new ChangedEventArgs(someData));

 

Event documentation

Each event should have the following API comment:

    /// <summary>
    /// <para>
    /// Occurs .... 
    /// </para>
    /// </summary>

Example:

    /// <summary>
    /// <para>
    /// Occurs immediately after the data has changed. 
    /// </para>
    /// </summar>
    event EventHandler<ChangedEventArgs> Changed;

 

 

Each EventArgs class should have following API comment:

    /// <summary>
    /// <para>
    /// Provides data for the <see cref="..."/> event.
    /// </para>
    /// </summary>

Example:

    /// <summary>
    /// <para>
    /// Provides data for the <see cref="IExample.Changed"/> event.
    /// </para>
    /// </summary>
    public class ChangedEventArgs : EventArgs

  

Each event handling method should have the following API comment:

    /// <summary>
    /// <para>
    /// Handles the <see cref="..."/> event by ....
    /// </para>
    /// </summary>
    /// <param name="sender">
    /// <para>
    /// The source of the event.
    /// </para>
    /// </param>
    /// <param name="e">
    /// <para>
    /// A <see cref="..."/> that contains the event data.
    /// </para>
    /// </param>

Example:

    /// <summary>
    /// <para>
    /// Handles the <see cref="IExample.Changed"/> event by ....
    /// </para>
    /// </summary>
    /// <param name="sender">
    /// <para>
    /// The source of the event.
    /// </para>
    /// </param>
    /// <param name="e">
    /// <para>
    /// A <see cref="ChangedEventArgs"/> that contains the event data.
    /// </para>
    /// </param>
    private void HandleEventIExampleChanged(object sender, ChangedEventArgs e)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值