关于静态事件 static event 的二三事

简介:

很多人都知道事件,一般定义一个事件是这样的写法

public event EventHandler OneEvent;

但是如果这样定义的话就需要进行null判断了

于是很多人这样定义事件:

public event EventHandler OneEventNeverNull = (o, e) => { };

 

这样就不需要判断null了。

 

上面的事件你可以把它认为是实例事件. 我们这里要谈的是静态事件(static event).

静态事件和实例事件的区别是加了个static 关键字,可别小看这个关键字,区别大了。

 

首先静态事件的定义为:

public static event EventHandler OneStaticEvent;

 

如果想要注册事件的话,那么必须使用类。

image

 

在.net 的事件里面,绝大多数是实例事件,但是却存在极少数的静态事件。

 

关于静态事件StackOverflow 上面有篇文章讨论它

地址如下:http://stackoverflow.com/questions/7045595/how-do-static-events-compare-to-non-static-events-in-c

 

我个人认为答案都不错,选了几个,试着翻译如下:

大部分的面向对象程序都可以被认为是消息的传递。

一个方法调用就是调用者发送给被调用者的携带参数的一个消息,和一个使用return value 做为返回值的消息。

一个事件是从source到订阅者的一个消息。因此就有两个实例参与其中,一个用来发送消息,另一个接收它。

但是静态事件,没有发送的实例(只是一个类型,它可能是也可能不是一个class)。

 

使用 静态事件的时候,要谨记,当一个对象订阅了一个静态事件,事件就持有了这个对象的引用,这就意味着你必须非常小心的显式的取消订阅事件,因为静态事件保留了对象引用,所以这些对象就永远不会被回收,你很可能碰到内存泄漏。

 

这些答案都说明了静态事件的一些特性。总结下:

1:静态事件没有发送的实例对象。

2:静态事件必须取消订阅,否则对象无法释放,事实上任何事件都应该取消订阅,有始有终。

 

对于第二点没有什么好考虑的,可是第一点?

静态事件没有发送的实例?

a:这代表静态事件不需要实例就可以,它代表的是类级别的事件。

b:这代表静态事件没有实例,或者说无法获取这个类的实例,所以使用静态事件。

 

从这两个理解,我们可以知道什么时候应该使用静态事件了。

a:从面向对象的角度,如果一个对象只想获取事件的通知,而不关心是谁发送的,它只关心事件发生。

b:这个类没有实例?,什么类没有实例???,静态类,抽象类,或者是一些特殊的类。

 

好了,我不卖关子了,让我们看看framework里面的静态事件吧,代码如下:

Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();

foreach (Assembly assembly in assemblies)
{
    foreach (Type type in assembly.GetTypes())
    {
        EventInfo[] events = type.GetEvents(BindingFlags.Public | BindingFlags.Static);
        if (events.Length > 0)
        {
            Console.WriteLine(type.ToString());
        }
    }
}
结果如下:
 

 

微软的开发人员只为这些类定义了静态事件,最后一个是我自己写的,我们看下这些究竟是些什么类。

 

System.Console

静态类,无法获取类的实例,所以静态事件。


System.Threading.Tasks.TaskScheduler

抽象类,它的静态事件定义如下:

//     当出错的 System.Threading.Tasks.Task 的未观察到的异常将要触发异常升级策略时发生,默认情况下,这将终止进程。
        public static event EventHandler<UnobservedTaskExceptionEventArgs> UnobservedTaskException;

只要应用程序注册了 UnobservedTaskException 事件,任何TaskScheduler的子类在发生exception的时候,都会通知到应用程序。


System.Diagnostics.Eventing.EventProviderDataStream

没找到。。。


System.Diagnostics.Contracts.Contract

静态类,无法获取类的实例,所以静态事件。


System.Windows.Forms.Application

密封类,构造函数为私有,外界无法直接获取Application 的实例。


System.Windows.Forms.ToolStripManager

密封类,构造函数为私有,外界无法直接获取实例。


System.ComponentModel.TypeDescriptor

密封类,构造函数为私有,外界无法直接获取实例。


Microsoft.Win32.SystemEvents

密封类,构造函数为私有,外界无法直接获取实例。

 

System.Net.NetworkInformation.NetworkChange

密封类,构造函数为私有,外界无法直接获取实例。 

StaticEventDemo.Test

出现的理由:在某天夜晚,我自己想当然的写下的没有经过思考的一个静态事件。

 

你知道微软使用静态事件的策略了吗?,只有在不能获取实例的情况下才选择静态事件。

 

有趣的一件事:本人在baidu下搜索:static event, 看到了一篇文章:

net 在类中的Event事件,为什么可以定义为static?而委托类型却不可以

也可以在这里http://www.2cto.com/kf/201110/108280.html看到代码。

 

我看到了下面的这段:

private void button1_Click(object sender, EventArgs e) 

            clsEvent clsevent = new clsEvent(); 
            //改变属性,从而激发事件。 
            clsevent.StrContent = this.textBox1.Text; 

 

我很想说,在改变属性前,是不是要注册点什么啊,我想这就是他为什么定义为static event的原因吧。

 

总结:

在无法获取实例的情况下,又想获得通知,应该使用静态事件。

不管发送者是谁,只考虑接收事件。

静态事件一定要取消订阅,否则内存泄漏。

想要获取静态类的通知时,使用静态事件。

想要得到静态属性和方法的通知的时候。






本文转自LoveJenny博客园博客,原文链接:http://www.cnblogs.com/LoveJenny/archive/2013/01/30/2882383.html,如需转载请自行联系原作者
目录
相关文章
|
2月前
|
JavaScript 前端开发 Java
v-if和v-show的区别?使用场景?v-if状态改变调用钩子函数的示例
这篇文章详细阐述了Vue中`v-if`和`v-show`指令的共同点、区别、使用场景以及它们在组件和普通元素上附属时的不同表现,并通过示例展示了状态改变时对钩子函数调用的影响。
v-if和v-show的区别?使用场景?v-if状态改变调用钩子函数的示例
|
4月前
|
C#
C#||委托和事件的实例
C#||委托和事件的实例
|
5月前
|
消息中间件 存储 API
【C/C++】回调函数详解&注册窗口类&LRESULT & CALLBACK详解以及游戏中的应用
【C/C++】回调函数详解&注册窗口类&LRESULT & CALLBACK详解以及游戏中的应用
209 0
是否可以从一个static方法内部发出对非static方法的调用?
这里其实问的是静态方法和非静态方法的区别: 静态方法和非静态方法的区别可以总结如下:
755 0
|
安全 编译器 C#
C#基础知识学习之 ✨ 委托(delegate) 与 事件(event) 之间的介绍
委托(delegate) 与 事件(event) 🔥 前言🙏 在之前的文章里介绍了C#中的委托(delegate) (Action、Func、Predicate)的基本含义及用法 那本篇文章在这里还要介绍一个跟委托有很大关系的小伙伴——C#中的 事件(event)🎅 事件跟委托是有很大联系的,所以也就导致很容易分不清他们两个,以及什么时候用这两个 上面有博客提到委托,想单独了解委托的可以去看一下,本篇文章主要说一下 什么是事件 🎄 以及 事件与委托的区别🎁
C#基础知识学习之 ✨ 委托(delegate) 与 事件(event) 之间的介绍
Revit空闲事件(Idling Event)增强和外部事件(External Event)
Revit空闲事件(Idling Event)增强和外部事件(External Event)
Revit空闲事件(Idling Event)增强和外部事件(External Event)
|
前端开发
前端工作总结142-element上传组件时候的钩子--event里面有数据参数
前端工作总结142-element上传组件时候的钩子--event里面有数据参数
71 0
前端工作总结142-element上传组件时候的钩子--event里面有数据参数
|
开发工具
定义无处不在的 Event 事件之 CloudEvents
Event 事件无处不在,然而如果没有一套事件统一的定义标准,那么对于事件处理的开发者来说无疑是痛苦的。CloudEvent 的出现统一了事件的标准,本篇文章简要介绍了这一标准规范协议,以及实际场景中使用的方式。
5343 1
是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?
不可以,静态方法只能访问静态成员,因为非静态方法的调用要先创建对象,在调用静态方法时可能对象并没有被初始化。
1056 0