7 ответов:
это действительно зависит от того, что вы собираетесь на:
#if DEBUG: код здесь даже не достигнет IL при выпуске.[Conditional("DEBUG")]: этот код достигнет IL, однако звонки метод будет опущен, если 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. }
#если отладка пример: я использую это при попытке настроить различные привязки для связи WCF.
#if DEBUG public const String ENDPOINT = "Localhost"; #else public const String ENDPOINT = "BasicHttpBinding"; #endifв первом примере код все существует, но просто игнорируется, если отладка не включена. Во втором примере конечная точка const устанавливается в "Localhost" или "BasicHttpBinding" в зависимости от того, установлена ли отладка или нет.
обновление: Я обновляю этот ответ, чтобы прояснить важный и сложный момент. Если вы решите использовать
ConditionalAttributeимейте в виду, что звонки опущено во время компиляции, и не выполнения. То есть:папку "MyLibrary".dll
[Conditional("DEBUG")] public void A() { Console.WriteLine("A"); B(); } [Conditional("DEBUG")] public void B() { Console.WriteLine("B"); }когда библиотека компилируется в режиме выпуска (т. е. без символа отладки), она всегда будет иметь вызов
B()внутриA()опущено, даже если вызовA()включено, потому что DEBUG определяется в вызывающей сборке.
ну, стоит отметить, что они вовсе не означают одно и то же.
Если символ debug не определен, то в первом случае
SetPrivateValueсам не будет называться... тогда как во втором случае он будет существовать, но любой абоненты у тех, кто скомпилирован без символа отладки, эти вызовы будут опущены.Если код и все его вызывающие элементы находятся в одной сборке, это различие меньше важно-но это значит, что в первом дело у вас и нужно
#if DEBUGвокруг вызов код, а также.лично я бы рекомендовал второй подход-но вы должны держать разницу между ними ясно в вашей голове.
Я уверен, что многие не согласятся со мной, но проведя время в качестве сборки парень постоянно слышит "но это работает на моей машине!- Я придерживаюсь той точки зрения, что Вы тоже никогда не должны ее использовать. Если вам действительно нужно что-то для тестирования и отладки, найдите способ сделать эту тестируемость отдельной от фактического производственного кода.
абстрактные сценарии с издевательствами в модульных тестах, сделать один от версии вещей для одного от сценариев, которые вы хотите проверить, но не ставьте тесты для отладки в код для двоичных файлов, которые вы тестируете и пишете для производственного выпуска. Эти отладочные тесты просто скрывают возможные ошибки от разработчиков, поэтому они не будут найдены до конца процесса.
С первым примером,
SetPrivateValueне будет существовать в сборке, еслиDEBUGне определен, со вторым, например, звонки доSetPrivateValueне будет существовать в сборке, еслиDEBUGне определен.в первом примере вам нужно будет обернуть все вызовы в
SetPrivateValueС#if DEBUGкак хорошо.со вторым примером, вызовы
SetPrivateValueбудет опущен, но имейте в виду, чтоSetPrivateValueсам по себе все равно будет скомпилирован. Это полезно, если вы строите библиотека, поэтому приложение, ссылающееся на вашу библиотеку, все еще может использовать вашу функцию (если условие выполнено).если вы хотите пропустить вызовы и сохранить пространство вызываемого абонента, вы можете использовать комбинацию двух методов:
[System.Diagnostics.Conditional("DEBUG")] public void SetPrivateValue(int value){ #if DEBUG // method body here #endif }
предположим, что ваш код также имел
#elseоператор, который определил нулевую функцию заглушки, обращаясь к одной из точек Джона Скита. Есть и второе важное различие между ними.предположим
#if DEBUGилиConditionalфункция существует в DLL, на которую ссылается ваш основной исполняемый файл проекта. Используя#if, оценка условного будет выполнена в отношении параметров компиляции библиотеки. Используя оценка условное будет выполняться с учетом настроек компиляции вызывающего устройства.
У меня есть расширение SOAP WebService для регистрации сетевого трафика с помощью пользовательского [TraceExtension]. Я использую это только для отладочных сборок и исключить из выпусков. Использовать #если отладки для обертывания, таким образом, атрибут [TraceExtension] удалением его из релизных сборках.
#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(...)
Comments