#si DEPURACIÓN vs. Condicional("DEPURACIÓN")

Resuelto Lucas B asked hace 14 años • 8 respuestas

Cuál es mejor usar y por qué en un proyecto grande:

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

o

[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value)
{ ... }
Lucas B avatar Sep 24 '10 22:09 Lucas B
Aceptado

Realmente depende de lo que estés buscando:

  • #if DEBUG: El código aquí ni siquiera llegará a IL en el momento de su publicación.
  • [Conditional("DEBUG")]: Este código llegará al IL; sin embargo, las llamadas al método se omitirán a menos que se establezca DEBUG cuando se compila la persona que llama.

Personalmente uso ambos dependiendo de la situación:

Condicional("DEBUG") Ejemplo: uso esto para no tener que volver atrás y editar mi código más adelante durante el lanzamiento, pero durante la depuración quiero estar seguro de no haber cometido ningún error tipográfico. Esta función comprueba que escribo correctamente el nombre de una propiedad cuando intento utilizarla en mis elementos 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));
}

Realmente no desea crear una función usando #if DEBUGa menos que esté dispuesto a envolver cada llamada a esa función con lo mismo #if DEBUG:

#if DEBUG
    public void DoSomething() { }
#endif

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

versus:

[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 Ejemplo de DEBUG: lo uso cuando intento configurar diferentes enlaces para la comunicación WCF.

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

En el primer ejemplo, todo el código existe, pero simplemente se ignora a menos que DEBUG esté activado. En el segundo ejemplo, el punto final constante se establece en "Localhost" o "BasicHttpBinding" dependiendo de si DEBUG está configurado o no.


Actualización: estoy actualizando esta respuesta para aclarar un punto importante y complicado. Si elige utilizar ConditionalAttribute, tenga en cuenta que las llamadas se omiten durante la compilación y no en el tiempo de ejecución . Eso es:

MyLibrary.dll

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

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

Cuando la biblioteca se compila en modo de lanzamiento (es decir, sin símbolo DEBUG), siempre se omitirá la llamada a B()desde dentro A(), incluso si se incluye una llamada a A()porque DEBUG está definido en el ensamblado que llama.

myermian avatar Sep 24 '2010 15:09 myermian

Bueno, vale la pena señalar que no significan lo mismo en absoluto.

Si el símbolo DEBUG no está definido, entonces en el primer caso SetPrivateValueno se llamará a sí mismo... mientras que en el segundo caso existirá, pero se omitirán esas llamadas a cualquier llamante que esté compilado sin el símbolo DEBUG.

Si el código y todos los llamadores están en el mismo ensamblado, esta diferencia es menos importante, pero significa que en el primer caso también es necesario tener #if DEBUGcerca el código de llamada .

Personalmente, recomendaría el segundo enfoque, pero es necesario tener clara la diferencia entre ellos.

Jon Skeet avatar Sep 24 '2010 15:09 Jon Skeet

Estoy seguro de que muchos no estarán de acuerdo conmigo, pero después de haber pasado tiempo como constructor escuchando constantemente "¡Pero funciona en mi máquina!", Tomo el punto de vista de que prácticamente nunca deberías usar ninguno de los dos. Si realmente necesita algo para probar y depurar, encuentre una manera de separar esa capacidad de prueba del código de producción real.

Resuma los escenarios con burlas en las pruebas unitarias, cree versiones únicas de las cosas para los escenarios únicos que desea probar, pero no incluya pruebas de depuración en el código de los archivos binarios que prueba y escribe para el lanzamiento en producción. Estas pruebas de depuración simplemente ocultan posibles errores a los desarrolladores para que no se encuentren hasta más adelante en el proceso.

Jimmy Hoffa avatar Sep 24 '2010 16:09 Jimmy Hoffa