Что лучше использовать и почему в большом проекте:
#if DEBUG
public void SetPrivateValue(int value)
{ ... }
#endif
или
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value)
{ ... }
c#
debugging
preprocessor
debug-symbols
Лукас Б
источник
источник
Ответы:
Это действительно зависит от того, что вы собираетесь:
#if DEBUG
: Код здесь даже не достигнет IL при выпуске.[Conditional("DEBUG")]
: Этот код достигнет IL, однако вызовы метода будут опущены, если только DEBUG не будет установлен при компиляции вызывающей стороны.Лично я использую оба в зависимости от ситуации:
Условный («DEBUG») пример: я использую это, чтобы мне не пришлось возвращаться и редактировать свой код позже во время выпуска, но во время отладки я хочу быть уверенным, что я не сделал никаких опечаток. Эта функция проверяет, правильно ли я ввожу имя свойства при попытке использовать его в своем материале INotifyPropertyChanged.
Вы действительно не хотите создавать функцию с использованием,
#if DEBUG
если вы не готовы обернуть каждый вызов этой функции одним и тем же#if DEBUG
:против:
#if Пример DEBUG: я использую это при попытке установить различные привязки для связи WCF.
В первом примере весь код существует, но он просто игнорируется, если не включен DEBUG. Во втором примере const ENDPOINT устанавливается в «Localhost» или «BasicHttpBinding» в зависимости от того, установлен ли DEBUG или нет.
Обновление: я обновляю этот ответ, чтобы прояснить важный и хитрый момент. Если вы решите использовать
ConditionalAttribute
, имейте в виду, что вызовы пропускаются во время компиляции, а не во время выполнения . Это:MyLibrary.dll
Когда библиотека скомпилирована с использованием режима выпуска (т. Е. Без символа DEBUG), она будет всегда пропускать вызов
B()
изнутриA()
, даже если вызовA()
включен, потому что DEBUG определен в вызывающей сборке.источник
Что ж, стоит отметить, что они совсем не имеют в виду одно и то же.
Если символ DEBUG не определен, то в первом случае
SetPrivateValue
сам не будет называться ... в то время как во втором случае она будет существовать, но любые абоненты , которые компилируются без символа DEBUG будут иметь те вызовы , опущенные.Если код и все его вызывающие объекты находятся в одной сборке, это различие не так важно, но это означает, что в первом случае вам также необходимо иметь дело
#if DEBUG
с вызывающим кодом.Лично я бы порекомендовал второй подход, но вы должны четко понимать разницу между ними.
источник
Я уверен, что многие со мной не согласятся, но, проведя время в качестве строителя, постоянно слышавшего: «Но это работает на моей машине!», Я считаю, что вы тоже почти никогда не должны его использовать. Если вам действительно нужно что-то для тестирования и отладки, найдите способ отделить тестируемость от реального производственного кода.
Абстрагируйте сценарии с использованием насмешек в модульных тестах, создайте уникальные версии для сценариев, которые вы хотите протестировать, но не помещайте тесты для отладки в код для двоичных файлов, которые вы тестируете и пишете для промышленного выпуска. Эти отладочные тесты просто скрывают возможные ошибки от разработчиков, поэтому они не обнаруживаются в процессе.
источник
#if debug
или подобная конструкция в вашем коде?#if DEBUG
чтобы мы не случайно спамили других во время тестирования системы, которая должна передавать электронную почту как часть процесса. Иногда это правильные инструменты для работы :)Этот также может быть полезен:
источник
Debugger.IsAttached
должен вызываться во время выполнения даже в сборках выпуска.В первом примере,
SetPrivateValue
не будет существовать в сборке , еслиDEBUG
не определено, то со вторым , например, требует , чтобыSetPrivateValue
не будет существовать в сборке , еслиDEBUG
не определено.В первом примере, вам придется обернуть любые звонки
SetPrivateValue
с#if DEBUG
а.Во втором примере вызовы
SetPrivateValue
будут опущены, но имейте в виду , чтоSetPrivateValue
сам по себе все равно будет скомпилирован. Это полезно, если вы создаете библиотеку, поэтому приложение, ссылающееся на вашу библиотеку, все еще может использовать вашу функцию (если выполняется условие).Если вы хотите пропустить вызовы и сэкономить место вызываемого абонента, вы можете использовать комбинацию из двух методов:
источник
#if DEBUG
вокругConditional("DEBUG")
не удаляют вызовы этой функции, она только удаляет функцию из IL ALLtogether, так что вы все еще есть вызов функции , которая не существует (ошибки компиляции).Давайте предположим, что в вашем коде также есть
#else
оператор, который определил нулевую функцию-заглушку, адресованную одному из пунктов Джона Скита. Есть второе важное различие между ними.Предположим, что функция
#if DEBUG
илиConditional
существует в DLL, на которую ссылается исполняемый файл вашего основного проекта. Используя#if
, оценка условного выражения будет выполняться с учетом параметров компиляции библиотеки. ИспользуяConditional
атрибут, оценка условия будет выполняться с учетом параметров компиляции вызывающего.источник
У меня есть расширение SOAP WebService для регистрации сетевого трафика с использованием пользовательских
[TraceExtension]
. Я использую это только для отладочных сборок и опускаю из сборок выпуска . Используйте атрибут,#if DEBUG
чтобы обернуть[TraceExtension]
атрибут, удалив его из сборок Release .источник
Обычно вам это нужно в Program.cs, где вы решаете запустить Debug для кода без отладки, и это тоже в основном в Windows Services. Поэтому я создал поле IsDebugMode только для чтения и установил его значение в статическом конструкторе, как показано ниже.
источник