Как компилятор C # удаляет Debug.Assert из сборок выпуска?

Я недавно просматривал некоторый код и размышлял, нужно ли мне быть осторожным с выражениями, помещенными в операторы 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 специальным или является можно ли создавать свои собственные методы с аналогичной обработкой?
  • Есть ли здесь какие-нибудь способы "обмануть" препроцессор? Более того, существуют ли ситуации, с которыми можно столкнуться в реальном коде, когда это может быть проблематично?
24
задан Scott Wegner 21 April 2011 в 22:31
поделиться