#если отладка и условная("отладка")



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



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


или



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

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 вокруг вызов код, а также.

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

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

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

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

if (Debugger.IsAttached)
{
...
}

С первым примером,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

    Ничего не найдено.