首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么事件2的圈复杂度?

为什么事件2的圈复杂度?
EN

Stack Overflow用户
提问于 2017-03-26 05:06:14
回答 1查看 156关注 0票数 3

我正在检查应用程序中的圈复杂度,目的是测试任何大于1的圈复杂度。

我看到的是,一个非常简单的事件的add访问器的圈复杂度为2,这是为什么?是因为add方法首先检查回调方法是否已经注册了吗?

我创建了一个非常简单的计算器应用程序来复制这种行为。我有一个名为CalculateComplete的事件,它在计算()方法完成时触发。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-26 06:37:00

如果有某个类具有某些事件,例如

代码语言:javascript
复制
class SomeClass
{
    public event Action<int> SomeEvent;
}

然后,为event方法生成的IL代码是:

代码语言:javascript
复制
SomeClass.add_SomeEvent:
IL_0000:  ldarg.0     
IL_0001:  ldfld       UserQuery+SomeClass.SomeEvent
IL_0006:  stloc.0     
IL_0007:  ldloc.0     
IL_0008:  stloc.1     
IL_0009:  ldloc.1     
IL_000A:  ldarg.1     
IL_000B:  call        System.Delegate.Combine
IL_0010:  castclass   System.Action<System.Int32>
IL_0015:  stloc.2     
IL_0016:  ldarg.0     
IL_0017:  ldflda      UserQuery+SomeClass.SomeEvent
IL_001C:  ldloc.2     
IL_001D:  ldloc.1     
IL_001E:  call        System.Threading.Interlocked.CompareExchange<Action`1>
IL_0023:  stloc.0     
IL_0024:  ldloc.0     
IL_0025:  ldloc.1     
IL_0026:  bne.un.s    IL_0007
IL_0028:  ret

注意,在方法的末尾有一个Interlocked.CompareExchange()调用,后面跟着一个“分支(如果不相等)”。是的,有一个分支,因此它的圈复杂度为2。

你可能会问,为什么会这样?原因是代表是不可改变的。向委托添加方法时,不修改原始委托,但实际上是从现有的委托和提供的方法创建组合委托,并将其重新分配到事件中。见Delegate.Combine

除此之外,新的和旧的委托之间的交换必须是线程安全的,这就是为什么Interlocked.CompareExchange。如果交换失败,请再试一次。

为了提供帮助,我已经将IL翻译成C#:

代码语言:javascript
复制
public void add_SomeEvent(Action<int> arg1)
{
    var local0 = this.SomeEvent;
IL_0007:
    var local1 = local0;
    var local2 = (Action<int>)Delegate.Combine(local1, arg1);
    local0 = Interlocked.CompareExchange(ref this.SomeEvent, local2, local1)
    if (local0 != local1) goto IL_0007;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43025238

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档