[英]How can the cyclomatic complexity be 27 in a method with 13 event handler subscriptions?
我们有这个代码,排序:
private void InitializeEvents()
{
this.Event1 += (s,e) => { };
this.Event2 += (s,e) => { };
this.Event3 += (s,e) => { };
this.Event4 += (s,e) => { };
this.Event5 += (s,e) => { };
this.Event6 += (s,e) => { };
this.Event7 += (s,e) => { };
this.Event8 += (s,e) => { };
this.Event9 += (s,e) => { };
this.Event10 += (s,e) => { };
this.Event11 += (s,e) => { };
this.Event12 += (s,e) => { };
this.Event13 += (s,e) => { };
}
VS10 Ultimate 中的代码分析说“圈复杂度为 27”。 删除其中一行使圈复杂度为 25。
没有分支正在进行,这怎么可能?
请记住,代码分析正在查看程序集中的 IL,而不是源代码。 IL 中没有任何内容本身支持 lambda 表达式,因此它们是编译器的一种构造。 您可以在此处找到输出内容的详细信息。 但基本上你的 lambda 表达式变成了一个私有的静态类,它是一个匿名委托。 但是,不是每次在代码中引用匿名委托时创建一个实例,而是缓存委托。 因此,每次分配 lambda 表达式时,它都会检查是否已创建该 lambda 委托的实例,如果已创建,则使用缓存的委托。 这会在 IL 中生成一个 if/else,将复杂度增加 2。所以在这个函数中,复杂度是 1 + 2*(lambda express) = 1 + 2 *(13) = 27,这是正确的数字。
C# 编译器实际上为匿名方法(包括 lambda)生成了一些相当“有趣”的 IL。 对于每一个,它都会创建一个私有字段,然后在消费方法中为其分配值之前,它会检查该值是否为空,这会向已编译的方法添加一个 If 分支。 该代码度量工具应该忽略这个(http://social.msdn.microsoft.com/Forums/eu/vstscode/thread/8c17f569-5ee3-4d26-bf09-4ad4f9289705, https://connect.microsoft.com/VisualStudio /feedback/details/555560/method-using-many-lambda-expressions-causes-high-cyclomatic-complexity ),我们希望它最终会。 目前,如果您认为这是一个误报,您几乎必须忽略该问题。
最好的猜测是,这可能是由于上面的语句被转换为事件访问器格式,即
class MyClass
{
private event EventHandler MyPrivateEvent;
public event EventHandler MyEvent
{
add
{
MyPrivateEvent += value;
}
remove
{
MyPrivateEvent -= value;
}
}
}
有关事件访问器格式的讨论,请参阅http://msdn.microsoft.com/en-us/magazine/cc163533.aspx和http://www.switchonthecode.com/tutorials/csharp-tutorial-event-accessors 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.