C# 初始化事件与检查null
基本上这在我脑子里已经有一段时间了。。。我想听听你的意见 我读了Jon Skeet的一本很棒的书,名为:C#深入,第二版,在声明自定义事件时,有一个建议使用如下内容:C# 初始化事件与检查null,c#,C#,基本上这在我脑子里已经有一段时间了。。。我想听听你的意见 我读了Jon Skeet的一本很棒的书,名为:C#深入,第二版,在声明自定义事件时,有一个建议使用如下内容: public event Action<string> MyEvent = delegate { }; 我们可以简单地称之为: this.MyEvent("OMG osh"); 我们的代码将简单地工作 当您声明这样的事件时,事件将使用空委托进行初始化,因此我们不需要检查null 这是声明事件的另一种方式,它们是等价
public event Action<string> MyEvent = delegate { };
我们可以简单地称之为:
this.MyEvent("OMG osh");
我们的代码将简单地工作
当您声明这样的事件时,事件将使用空委托进行初始化,因此我们不需要检查null
这是声明事件的另一种方式,它们是等价的
private Action<string> myDelegate;
public event Action<string> MyEvent
{
add
{
this.myDelegate += value;
}
remove
{
this.myDelegate -= value;
}
}
私人行动myDelegate;
公共事件行动
{
添加
{
this.myDelegate+=值;
}
去除
{
this.myDelegate-=值;
}
}
有关更多信息:
我刚刚和一些同事在工作中讨论了这个话题,他们认为有时我们需要立即清除所有活动订阅,我们可以简单地将null赋值给后面的委托,如果我们想继续使用相同的模式,就必须用一个空委托重新初始化事件。他们还问在多线程场景中会发生什么,这就是我提出这个问题的主要原因
问题
If
条件,从而删除跳转语句。就整体性能而言,这不是更好吗干杯首先:你确定你没有过早地优化吗?您是否确实面临性能问题,因为在触发事件时,您不是在检查null,而是在调用另一个空方法?如果没有,那么我建议你放弃这个问题 现在,对于您的问题:我认为可以肯定地说,检查null比多余的方法调用更便宜,因此如果您希望获得尽可能好的性能,那么Jon Skeet方便的
委托{}
模式可能不适合您
当涉及多线程时,一个更重要的问题是定义每个事件处理程序将在哪个线程/哪个上下文(例如,SynchronizationContext
)上调用。您应该能够将此决定权留给事件的每个使用者,因为有些事件处理程序不关心,而另一些则希望转发到正确的上下文(例如通过SynchronizationContext.Post
)
如果您决定检查null,请注意以下内容:
if (this.MyEvent != null)
{
this.MyEvent("OMG osh");
}
if (this.MyEvent != null)
{
this.MyEvent("OMG osh");
}
建议在多线程方案中,改为执行以下操作:
Action<string> handlers = this.MyEvent;
if (handlers != null)
{
handlers("OMG osh");
}
Action handlers=this.MyEvent;
if(处理程序!=null)
{
装卸工(“OMG osh”);
}
也就是说,首先将委托复制到局部变量中。这是因为在检查null期间,委托变量可能会被另一个线程操纵。(我不确定这是否真的有必要,但这是建议的模式。)
离题:我想你有一个小错: [W] 当您声明一个事件时,[正在]实际发生的是您正在声明一个
委托
和一个事件
这是正确的,但值得注意的是,对于CLI来说,事件只是几个方法的组合(例如,
add
、remove
、raise
以及其他可能的访问器)。几乎所有其他东西实际上都是特定于语言的。例如,C#中的事件只不过是一个委托,与一些访问器方法配对,以及对委托可以执行的操作的一些附加约束(即+=
和-=
是从声明事件的类型之外对委托执行的唯一有效操作).比起开发团队的可读性和期望,我对性能更感兴趣。您不希望其他不了解使用模式的开发人员认为,“啊!我看到有人忘记正确使用委托调用并检查null”
我一直都明白,要处理多线程场景,您仍然需要制作底层委托的本地副本,这样您就可以向所有订阅者发出请求,即使在调用订阅者时,在迭代过程中订阅者列表发生了更改
尽管如此,我仍然想知道如何使用这个扩展方法来保存样板代码(对于多个参数使用重载)
如果订阅者不需要知道是谁触发了事件,我倾向于选择Action而不是EventHandler事件
public static class ActionExtension
{
public static void SafeInvoke<T>(this Action<T> action, T arg)
{
var temp = action;
if (temp != null)
{
temp(arg);
}
}
}
public event Action<string> InterestingEvent;
// event invoker
InterestingEvent.SaveInvoke("Boo!");
公共静态类ActionExtension
{
公共静态void SafeInvoke(此操作,T参数)
{
var-temp=动作;
如果(温度!=null)
{
温度(arg);
}
}
}
公共事件行动兴趣事件;
//事件调用程序
SaveInvoke(“Boo!”);
Erm。。。对不起,但是。。。你的问题是什么?这都是非常有趣的聊天内容,但问答网站也是如此。你能把引用的文本格式化得更清楚些吗?(选择并使用[“]
按钮)这篇文章的结尾,我只是强调我想阅读你对这个主题的评论->不是正确的问题。@Jupaol我建议将你的问题移到文本的开头,然后在下面添加你的其他评论。