NDepend CQL сообщает о методах как о неправильном использовании Boxing/Unboxing

В NDepend 4 (v4.1.0.6871) я использую запрос дизайна по умолчанию «Следует избегать упаковки/распаковки»:

warnif percentage > 5 from m in Application.Methods where
    m.IsUsingBoxing ||
    m.IsUsingUnboxing
select new { m, m.NbLinesOfCode, m.IsUsingBoxing, m.IsUsingUnboxing }

Он сообщает, что следующий метод (вдохновленный и украденный из MiscUtil Джона Скита) использует заниматься боксом:

public static void ThrowIfNull<T>(this T target, string name) where T : class
{
  if (target == null)
  {
    throw new ArgumentNullException(name ?? string.Empty);
  }
}

Я не понимаю, как этот метод может использовать бокс. Я нигде не использую приведение.

Я попробовал следующую версию на тот случай, если оператор объединения с нулевым значением как-то за кулисами использует бокс:

public static void ThrowIfNull<T>(this T target, string name) where T : class
{
  if (target == null)
  {
    throw new ArgumentNullException(name);
  }
}

... но и с этим мне не повезло, NDepend все же сообщил, что метод использует бокс.

Любые идеи?


person Joseph Alcorn    schedule 03.08.2013    source источник


Ответы (1)


Декомпилируя этот метод с помощью .NET Reflector, мы видим, что этот метод действительно использует IL-инструкцию box. Несмотря на то, что вы используете универсальное ограничение class, компилятор по-прежнему выдает блок-инструкцию для проверки возможности проверки. Подробнее об этом здесь< /а>.

.method public hidebysig static void ThrowIfNull<class T>(!!T target, string name) cil managed
{
    .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor()
    .maxstack 2
    .locals init (
        [0] bool flag)
    L_0000: nop 
    L_0001: ldarg.0 
    L_0002: box !!T   <-----------
    L_0007: ldnull 
    L_0008: ceq 
    L_000a: ldc.i4.0 
    L_000b: ceq 
    L_000d: stloc.0 
    L_000e: ldloc.0 
    L_000f: brtrue.s L_0022
    L_0011: nop 
    L_0012: ldarg.1 
    L_0013: dup 
    L_0014: brtrue.s L_001c
    L_0016: pop 
    L_0017: ldsfld string [mscorlib]System.String::Empty
    L_001c: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string)
    L_0021: throw 
    L_0022: ret 
}
person Patrick from NDepend team    schedule 03.08.2013