Использование ConditionalAttribute также удаляет вычисление аргументов?

Я попробовал следующий код:

class Magic {
   [Conditional("DEBUG")]
   public static void DoMagic( int stuff )
   {
   }
   public static int ComputeMagic()
   {
      throw new InvalidOperationException();
   }
}
class Program
{
   static void Main(string[] args)
   {
      Magic.DoMagic(Magic.ComputeMagic());
   }
}

и похоже, что в Release build исключение не генерируется, поэтому не только вызов метода, отмеченного ConditionalAttribute удаляется, но также исключается вычисление параметров.

Такое поведение гарантировано?

2 ответа

Решение

Да, оценка аргумента удаляется, когда DEBUG не определено (что типично для сборок Release).

С http://msdn.microsoft.com/en-us/library/aa664622%28v=vs.71%29.aspx:

Если символ определен, вызов включен; в противном случае вызов (включая оценку параметров вызова) опускается.

Да, все удалено. Это может быть полезно для избежания дорогостоящих вычислений, которые имеют отношение только к (скажем) ведению журнала, но это означает, что вы должны быть осторожны, чтобы не устранить необходимые побочные эффекты. Например:

Trace(SomethingCritical());

очень отличается от:

var result = SomethingCritical();
Trace(result);

или в вашем конкретном случае:

DoMagic(ComputeMagic()); // everything here done only if DEBUG symbol defined

против

var result = ComputeMagic(); // always done
DoMagic(result); // done only if DEBUG symbol defined

Из спецификации §17.4.2 (выделено мной):

Если символ определен, вызов включен; в противном случае вызов (включая оценку получателя и параметры вызова) пропускается.

Другие вопросы по тегам