我们都熟悉C#事件声明的恐怖.为了确保线程安全,标准是写这样的东西:
public event EventHandler SomethingHappened;
protected virtual void OnSomethingHappened(EventArgs e)
{
var handler = SomethingHappened;
if (handler != null)
handler(this, e);
}
Run Code Online (Sandbox Code Playgroud)
最近在这个板上的一些其他问题(我现在找不到),有人指出在这种情况下可以很好地使用扩展方法.这是一种方法:
static public class EventExtensions
{
static public void RaiseEvent(this EventHandler @event, object sender, EventArgs e)
{
var handler = @event;
if (handler != null)
handler(sender, e);
}
static public void RaiseEvent<T>(this EventHandler<T> @event, object sender, T e)
where T : EventArgs
{
var handler = @event;
if (handler != null)
handler(sender, e);
}
}
Run Code Online (Sandbox Code Playgroud)
有了这些扩展方法,你需要声明和引发一个事件就像这样: …
让我感到困惑的东西,但从来没有引起任何问题......推荐的事件发送方式如下:
public event EventHandler SomeEvent;
...
{
....
if(SomeEvent!=null)SomeEvent();
}
Run Code Online (Sandbox Code Playgroud)
在多线程环境中,此代码如何保证另一个线程不会更改SomeEvent检查null和事件调用之间的调用列表?
检查事件处理程序是否为null时,是否基于每个线程完成?
确保有人正在听这个事件就像这样:
EventSeven += new DivBySevenHandler(dbsl.ShowOnScreen);
Run Code Online (Sandbox Code Playgroud)
如果我在上面检查null的模式之后添加代码,那么为什么我需要一个空检查(从这个站点获取的代码).我错过了什么?
此外,事件和GC的规则是什么?
我总是这样调用事件
void onSomeEvent(string someArg) {
var h = this.EventName;
if (h != null) {
h(this, new MyEventArgs(someArg));
}
}
Run Code Online (Sandbox Code Playgroud)
今天VS 2015告诉我这可以简化:
MyEvent?.Invoke(this, new MyEventArgs(someArg));
Run Code Online (Sandbox Code Playgroud)
关于后一种方法的一些问题,我以前没见过:
?在事件名称之后检查处理程序是否为空?.Invoke()看起来很简单?.Invoke()第二个例子也是如此?这两个代码示例之间用于调用事件的区别是什么?
样品1
public void OnDataChanged()
{
if (DataChanged != null)
{
DataChanged(this);
}
}
Run Code Online (Sandbox Code Playgroud)
样本2
DataChanged.Invoke(this);
Run Code Online (Sandbox Code Playgroud)
我应该何时使用每种方法来调用自定义事件?为什么有时我尝试使用调用事件时会得到NullReferenceException DataChanged.Invoke(this),但是当我将事件调用转换为示例1中的方法时,DataChanged永远不会变为null?
我经常看到如下代码,并想知道是否有任何理由为事件使用局部变量,而不仅仅是使用事件本身.在那儿?
var handler = OnQueryComplete;
if (handler != null)
handler(this, new RepositoryEventArgs<T>(results));
Run Code Online (Sandbox Code Playgroud)