Недавно я просмотрел код и подумал, нужно ли быть осторожным с выражениями, размещенными внутри операторов Debug.Assert
, такими как дорогостоящие операции или те, у кого есть побочные эффекты. Однако, похоже, компилятор довольно умен в отношении полного удаления оператора Assert
и внутренних выражений.
Например, следующее будет выводиться только на отладочные сборки:
static void Main(string[] args)
{
Debug.Assert(SideEffect());
}
private static bool SideEffect()
{
Console.WriteLine("Side effect!");
return true;
}
И это будет жаловаться на то, что o
используется до инициализации в выпусках:
static void Main(string[] args)
{
object o;
Debug.Assert(Initialize(out o));
o.ToString();
}
private static bool Initialize(out object o)
{
o = new object();
return true;
}
Он даже, кажется, не согласен с такими выражениями (печать "После" в обоих случаях):
static void Main(string[] args)
{
if (false) Debug.Assert(true);
Console.WriteLine("After");
}
Я был немного удивлен, насколько умным является компилятор и его способность правильно обнаруживать случаи, когда удаляется Debug.Assert
. Поэтому мне было любопытно.
- Как точно удаляется оператор? Дерево выражений должно быть создано до того, как оператор будет удален, чтобы правильно выполнить вышеуказанный оператор
if
. - Является ли класс
System.Diagnostics.Debug
особенным здесь, или можно создать собственные методы с аналогичной обработкой? - Есть ли способы "обмануть" препроцессор здесь? Еще лучше, есть ситуации, с которыми можно столкнуться в реальном коде, где это может быть проблематично?