#if DEBUG против условного (“DEBUG”)

Что лучше использовать и почему, по большому проекту:

#if DEBUG public void SetPrivateValue(int value) { ... } #endif 

или

 [System.Diagnostics.Conditional("DEBUG")] public void SetPrivateValue(int value) { ... } 

    Это действительно зависит от того, что вы собираетесь делать:

    • #if DEBUG : Код здесь даже не дойдет до релиза IL.
    • [Conditional("DEBUG")] : этот код достигнет ИЛ, однако вызовы метода будут опущены, если DEBUG не будет установлен, когда собеседник будет скомпилирован.

    Лично я использую оба в зависимости от ситуации:

    Условный («DEBUG») Пример: я использую это, поэтому мне не нужно возвращаться и редактировать свой код позже во время выпуска, но во время отладки я хочу быть уверенным, что я не делал никаких опечаток. Эта функция проверяет, что я правильно набираю имя свойства при попытке использовать его в своих материалах INotifyPropertyChanged.

     [Conditional("DEBUG")] [DebuggerStepThrough] protected void VerifyPropertyName(String propertyName) { if (TypeDescriptor.GetProperties(this)[propertyName] == null) Debug.Fail(String.Format("Invalid property name. Type: {0}, Name: {1}", GetType(), propertyName)); } 

    Вы действительно не хотите создавать функцию, используя #if DEBUG если вы не захотите обернуть каждый вызов этой функции с помощью того же #if DEBUG :

     #if DEBUG public void DoSomething() { } #endif public void Foo() { #if DEBUG DoSomething(); //This works, but looks FUGLY #endif } 

    против:

     [Conditional("DEBUG")] public void DoSomething() { } public void Foo() { DoSomething(); //Code compiles and is cleaner, DoSomething always //exists, however this is only called during DEBUG. } 

    #if Пример DEBUG: я использую это при попытке установить различные привязки для связи WCF.

     #if DEBUG public const String ENDPOINT = "Localhost"; #else public const String ENDPOINT = "BasicHttpBinding"; #endif 

    В первом примере код все существует, но просто игнорируется, если не включен DEBUG. Во втором примере константа ENDPOINT установлена ​​в «Localhost» или «BasicHttpBinding» в зависимости от того, установлен ли DEBUG или нет.


    Обновление: я обновляю этот ответ, чтобы прояснить важный и сложный вопрос. Если вы решите использовать ConditionalAttribute , имейте в виду, что во время компиляции не выполняются вызовы, а не время выполнения . То есть:

    MyLibrary.dll

     [Conditional("DEBUG")] public void A() { Console.WriteLine("A"); B(); } [Conditional("DEBUG")] public void B() { Console.WriteLine("B"); } 

    Когда библиотека скомпилирована в режиме деблокирования (т. Е. Не имеет символа DEBUG), навсегда будет вызываться вызов B() из A() , даже если включен вызов A() поскольку DEBUG определен в вызывающей сборке ,

    Ну, стоит отметить, что они не означают одно и то же.

    Если символ DEBUG не определен, то в первом случае сам SetPrivateValue не будет вызываться … тогда как во втором случае он будет существовать, но любые вызывающие , которые скомпилированы без символа DEBUG, будут иметь эти пропущенные вызовы.

    Если код и все его вызывающие лица находятся в одной и той же сборке, это различие менее важно, но это означает, что в первом случае вам также необходимо иметь #if DEBUG вокруг кода вызова .

    Лично я бы порекомендовал второй подход, но вам нужно сохранить разницу между ними в своей голове.

    Я уверен, что многие со мной не согласятся, но, проведя время, когда парень по сборке постоянно слышит: «Но это работает на моей машине!», Я придерживаюсь мнения, что вы почти никогда не будете использовать его. Если вам действительно нужно что-то для тестирования и отладки, выясните способ сделать эту тестируемость отдельно от фактического производственного кода.

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

    Это также может быть полезно:

     if (Debugger.IsAttached) { ... } 

    В первом примере SetPrivateValue не будет существовать в сборке, если DEBUG не определен, а во втором примере вызовы SetPrivateValue не будут существовать в сборке, если DEBUG не определен.

    В первом примере вам нужно будет обернуть любые вызовы SetPrivateValue с помощью #if DEBUG .

    Во втором примере вызовы SetPrivateValue будут опущены, но имейте в SetPrivateValue что SetPrivateValue сам по-прежнему будет скомпилирован. Это полезно, если вы создаете библиотеку, поэтому приложение, ссылающееся на вашу библиотеку, все равно может использовать вашу функцию (если условие выполнено).

    Если вы хотите опустить вызовы и сохранить пространство вызываемого абонента, вы можете использовать комбинацию двух методов:

     [System.Diagnostics.Conditional("DEBUG")] public void SetPrivateValue(int value){ #if DEBUG // method body here #endif } 

    Предположим, что у вашего кода также был оператор #else который определял нулевую функцию заглушки, обращаясь к одной из точек Джона Скита. Второе важное различие между ними.

    Предположим, что функция #if DEBUG или Conditional существует в DLL, на которую ссылается ваш основной исполняемый файл проекта. Используя #if , оценка условного будет выполняться в отношении настроек компиляции библиотеки. Используя условный атрибут, оценка условного будет выполняться в отношении настроек компиляции invoker.

    У меня есть расширение SOAP WebService для регистрации сетевого трафика с помощью пользовательского [TraceExtension]. Я использую это только для сборки Debug и опускаю из сборки Release. Используйте #if DEBUG, чтобы обернуть атрибут [TraceExtension], тем самым удалив его из сборки Release.

     #if DEBUG [TraceExtension] #endif [System.Web.Service.Protocols.SoapDocumentMethodAttribute( ... )] [ more attributes ...] public DatabaseResponse[] GetDatabaseResponse( ...) { object[] results = this.Invoke("GetDatabaseResponse",new object[] { ... parmeters}}; } #if DEBUG [TraceExtension] #endif public System.IAsyncResult BeginGetDatabaseResponse(...) #if DEBUG [TraceExtension] #endif public DatabaseResponse[] EndGetDatabaseResponse(...) 
    Interesting Posts

    Конкатенация диапазона со значениями между

    Установите альфа-маску BufferedImage в Java

    Раскладка клавиатуры в случайном порядке в Windows 8

    Селекторы списков для объекта Objective-C

    Вариадические рекурсивные macros препроцессора – возможно ли это?

    Объявление переменной в операторе switch C #

    Знак предупреждения Thunderbird продолжает появляться

    Почему C # не использует арифметическую проверку переполнения по умолчанию?

    cc1plus: ошибка: непризнанная опция командной строки «-std = c ++ 11» с g ++

    Почему подключенные диски появляются снова после выхода из системы и обратно, а не после перезагрузки?

    Вращение нескольких изображений, вызывающих мерцание. Java Graphics2D

    Функция SUMIFS в Google Spreadsheet

    Практическое использование виртуальных функций в c #

    Можно ли написать шаблон для проверки существования функции?

    Изменение фонового изображения с помощью анимации CSS3

    Давайте будем гением компьютера.