#si DEPURACIÓN vs. Condicional("DEPURACIÓN")
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)
{ ... }
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 DEBUG
a 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.
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 SetPrivateValue
no 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 DEBUG
cerca el código de llamada .
Personalmente, recomendaría el segundo enfoque, pero es necesario tener clara la diferencia entre ellos.
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.