CS.RESOURCE.UNBOXING

Unboxing inside a loop

This checker reports a defect whenever a value is extracted from object inside a loop body due to unboxing. Unboxing is automatically applied by the compiler when an object is explicitly cast to a primitive type. This is considered a computationally expensive operation that can take several times longer than a simple primitive type assignment. The performance effect can be especially impactful when the conversion takes place within a loop. Klocwork detects auto-unboxing within a loop body and warns of its potential performance impact.

Vulnerability and risk

Unboxing can lead to reduced responsiveness of the software and potentially contribute to overall performance degradation of the software.

Mitigation and prevention

To prevent these negative effects, auto-unboxing should be avoided.

Vulnerable code example

Copy
  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 produces an issue report at line 8 indicating that, “Unboxing is applied at line 10 to 'test' which is explicitly converted to the primitive type 'int'.” In this case, unboxing is done within the loop, converting a constant integer value to an object first, before the ‘+’ operation with the object variable count.

Fixed code example

Copy
  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);
     }
   }
 }

In the fixed code, both the operands at line 11 are built-in integers in loop, so the issue is not reported.