首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么在用其他相关因素重新排列开关语句时,圈复杂度会发生变化?

为什么在用其他相关因素重新排列开关语句时,圈复杂度会发生变化?
EN

Stack Overflow用户
提问于 2013-10-19 05:45:23
回答 1查看 446关注 0票数 1

下面的方法的CC将生成为9

代码语言:javascript
复制
    Public Enum Fruits
        Apple
        Pineapple
        Banana
        PassionFruit
        Orange
        Melon
        Grape
        Mango
    End Enum


  Private Function Fruity(ByVal fruitType As Fruits)

        Select Case fruitType
            Case Fruits.Orange, Fruits.Banana
            Case Fruits.Melon
            Case Fruits.Mango
            Case Fruits.Pineapple
            Case Fruits.Passionfruit
            Case Fruits.Melon, Fruits.Apple
        End Select
    End Function

但是,当用户定义enum成员值时,则该方法的CC增加到14。

代码语言:javascript
复制
 Public Enum Fruits
        Apple = 1
        Pineapple = 3
        Banana = 4
        Passionfruit = 5
        Orange = 7
        Melon = 9
        Grape = 11
        Mango = 13
    End Enum

现在,假设我将select语句改为下面的select语句,那么这个方法的CC更改为7,但是与上面的select-case相比,可维护性指数略有下降。

代码语言:javascript
复制
 Select Case true
       Case fruitType= Fruits.Orange or fruitType= Fruits.Banana
       Case fruitType=Fruits.Melon
       Case fruitType=Fruits.Mango
       Case fruitType=Fruits.Pineapple
       Case fruitType=Fruits.Passionfruit
       Case fruitType=Fruits.Melon, Fruits.Apple
  End Select

在最后一个场景中,我将参数的数据类型更改为integer,并访问一个不同的Enum,称为蔬菜,其值为50。现在,该方法的CC上升到52。但是,如果我将土豆的值改为0或1,则CC保持在15。

代码语言:javascript
复制
  Public Enum Vegetables
   Potato = 50
  End Enum

  Private Function Fruity(ByVal fruitType As Integer)

        Select Case fruitType
            Case Fruits.Orange, Fruits.Banana
            Case Fruits.Melon
            Case Fruits.Mango
            Case Vegetables.Potato
            Case Fruits.Passionfruit
            Case Fruits.Melon, Fruits.Apple
        End Select
    End Function

这些都是在VS 2008团队系统版本的3.5SP1测试。我想知道为什么在这4种情况下CC会出现波动。

它与下面第二点有什么关系吗?因为如果我在第四种场景中删除掉掉的情况,CC就会下降到9。那么这是VS 2008中的一个bug吗?

关于Visual 2010的特别说明

使用Visual 2010计算代码度量时,可能存在不适用于Visual 2008的差异。在线文档(http://msdn.microsoft.com/en-us/library/ee703787.aspx)给出了以下原因:

  1. 函数包含一个或多个catch块。在Visual的早期版本中,catch块不包括在计算中。在Visual 2010中,将每个catch块的复杂性添加到函数的复杂性中。
  2. 该函数包含一个switch (在VB中选择Case )语句。Visual 2010和早期版本之间的编译器差异可以为某些包含失败案例的开关语句生成不同的MSIL代码。
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-10-19 06:50:41

圈复杂度计数是一个相当简单的特性,它只计算从代码生成的IL中出现的分支数。每个分支都会增加1。

您需要查看IL,从Visual命令提示符运行ildasm.exe实用程序。当您比较这些不同代码段的IL时,就会立即明白为什么复杂性计数会发生这样的变化。

  • 第一个版本为每个枚举生成一个带有一个条目的Opcodes.Switch。开关表中的每个条目对应于一个Case语句,并使复杂性计数增加1。
  • 下一个版本会增加开关表的大小。它为缺失的枚举值添加条目。这不适当地增加了复杂性计数,该工具只是不够聪明,无法识别虚拟条目,而且很难做到。
  • 您的上一个版本在枚举值中有太多的空白。编译器认识到Opcodes.Switch不再有效,并生成完全不同的代码,现在使用的是一系列If/ElseIf测试。降低复杂度。

只使用圈复杂度作为一个粗略的指导方针,它只是不够复杂,不足以证明剧烈的代码更改是合理的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19462829

复制
相关文章

相似问题

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