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 行目で指摘レポートを生成し、「プリミティブ型 'int' に明示的に変換される 'test' に、10 行目でボックス化解除が適用されている」ことを示します。この場合、ボックス化解除はループ内で行われており、オブジェクト変数 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 行目で両方のオペランドがループ内のビルトイン整数であるため、指摘は報告されません。