CS.RESOURCE.UNBOXING

循环内的拆箱

每当因拆箱而从循环体内的对象提取值时,此检查器都会报告缺陷。将对象显式转换为基元类型时,编译器会自动应用拆箱。这是一项要占用大量计算资源的运算,所需的时间可能会比简单的基元类型分配多出几倍。当转换在循环内发生时,造成的性能影响尤为重大。Klocwork 会检测循环体内的自动拆箱并针对其潜在的性能影响发出警告。

漏洞与风险

拆箱可能会导致软件的响应能力下降,并且可能引起软件的总体性能降低。

缓解与预防

为防止这些负面影响,应避免自动拆箱。

漏洞代码示例

复制
  using System;
  namespace AutoUnBox
  {
    class UnBox {
      public void Example1() {
              TestUnBox test = new TestUnBox();
  
        int count = 0;
        for (long i = 0; i < 10; i++) {
         count = (int)test + count;                 // CS.RESOURCE.UNBOXING
       }
     }
   }
   class TestUnBox {
 
     TestUnBox() {}
 
     private int value1 { set; get; }
 
     public static explicit operator int(TestUnBox v) {
       return value1;
     }
   }
 }

Klocwork 针对第 8 行生成问题报告,这表示“自动拆箱在第 10 行应用于显式转换为基元类型 int 的 test”。在此情况下,自动拆箱在循环内进行,首先将常量整数值转换为对象,然后通过对象变量 count 进行 + 运算。

修正代码示例

复制
  using System;
  namespace AutoUnBox
  {
    class UnBox {
      public void Example1() {
              TestAutoBox countObj = new TestAutoBox();
              TestAutoBox test = new TestAutoBox();
  
        int countValue = 0;
       for (long i = 0; i < 10; i++) {
         countObj = test + countObj;                 // no CS.RESOURCE.AUTOBOXING
       }
       countValue = (int) testObj;
     }
   }
   class TestUnBox {
 
     TestUnBox() {
       this.value1 = 0;
     }

     TestUnBox(int intValue) {
       this.value1 = intValue;
     }
 
     private int value1 { set; get; }
 
     public static implicit operator TestAutoBox(int v) {
       return new TestAutoBox(v);
     }
   }
 }

在经修正的代码中,第 11 行的两个操作数均为循环中的内置整数,因此未报告该问题。