2010-09-24 7 views
11

¿Cuál es la alternativa a tener código con compilación condicional en C#?Alternativas a la compilación condicional en C#

Tengo una clase que tiene un montón de código que se basa en # ifdef .. Después de algún tiempo mi código es ilegible.

Buscando técnicas de refactorización a utilizar para una mejor legibilidad y mantenimiento de código con muchos #if defs

+0

¿Por qué lo necesita en primer lugar? ¿Está relacionado con la información de depuración? – Aliostad

Respuesta

23

Una cosa es utilizar la ConditionalAttribute:

[Conditional("DEBUG")] 
public void Foo() 
{ 
    // Stuff 
} 

// This call will only be compiled into the code if the DEBUG symbol is defined 
Foo(); 

Es todavía la compilación condicional, pero basándose en atributos en vez que #ifdef, lo que lo hace generalmente más simple.

Otra alternativa es simplemente usar valores booleanos en tiempo de ejecución, en lugar de hacerlo todo en tiempo de compilación. Si pudieras darnos más detalles de lo que intentas lograr y cómo estás usando la compilación condicional, sería útil.

+0

En el caso de las impresiones de depuración que toman cadenas como argumentos, esas cadenas aún pueden ser internados en el ejecutable del programa a pesar de que ninguno de los parámetros se haya evaluado alguna vez. ¿Conoces una manera de obtener los mismos resultados que C++ "#define DebugPrint ((void) 0)" desde C#? –

+0

@Blake: ¿Has validado que eso es cierto? No lo esperaría, aunque puedo estar equivocado. –

1

El uso de ConditionalAttribute sería un comienzo. De lo contrario, bastante de lo que la gente suele hacer con la compilación condicional generalmente se puede manejar invirtiendo el control y/o el uso juicioso de las fábricas.

1

Polimorfismo.

Acérquelo de la misma manera que lo haría con cualquier código de espagueti con muchas ramas condicionales en la misma condición.

Resuma las diferencias en una clase base o interfaz.

Construya la clase concreta según la compilación (una #if). Pase el objeto concreto a su aplicación, y luego su aplicación llama a los métodos definidos en la interfaz.

6

Una alternativa es usar el ConditionalAttribute. El atributo condicional funciona de manera similar.

#define TRACE_ON 
using System; 
using System.Diagnostics; 

public class Trace 
{ 
    [Conditional("TRACE_ON")] 
    public static void Msg(string msg) 
    { 
     Console.WriteLine(msg); 
    } 
} 

public class ProgramClass 
{ 
    static void Main() 
    { 
     Trace.Msg("Now in Main..."); 
     Console.WriteLine("Done."); 
    } 
} 
6

Si se trata de un problema de código de lectura inversa, es posible considerar el uso calificador clase parcial de .Net y poner el código condicional en archivos separados, así que tal vez usted podría tener algo como esto ...

foo Cs:

public partial class Foo 
{ 
    // Shared Behavior 
} 

foo.Debug.cs:

#if DEBUG 
public partial class Foo 
{ 
    // debug Behavior 
} 
#endif 

foo.bar.cs:

#define BAR 
#if BAR 
public partial class Foo 
{ 
    // special "BAR" Behavior 
} 
#endif 

no estoy seguro de si está o no puede definir sus condicionales fuera del archivo de código sin embargo, por hacer algo como esto podría reducir la flexibilidad de la definiciones condicionales (p. ej. es posible que no pueda crear una rama condicional contra BAR en, por ejemplo, el archivo principal, y tener que mantener múltiples BAR definidas podría ponerse feo), así como requerir una cierta diligencia para ir a los archivos para habilitar/deshabilitar efectivamente ese bit de código.

Por lo tanto, utilizar este enfoque podría terminar presentando más complicaciones de las que resuelve, pero, dependiendo de su código, ¿podría ser útil?

0

SI la razón por la que está utilizando la compilación condicional se puede refactorizar fácilmente, puede considerar usar el Managed Extensibility Framework para cargar el código dinámicamente en función de las condiciones en el tiempo de ejecución.

0

Ampliando la respuesta de Jon, aunque existen varias limitaciones al usar el ConditionalAttribute, hay una ventaja significativa. Cuando la condición es falsa, las llamadas al método condicional se omiten. Por ejemplo, puede agregar cientos de llamadas a un sistema de registro, por ejemplo para la depuración, que pueden excluirse condicionalmente del código de producción. Cuando se excluyen, no hay gastos generales asociados con llamar a un método que no necesita ser llamado. Al usar #ifdef, tendría que ajustar cada llamada al sistema de registro para excluirlas condicionalmente.

Tenga en cuenta que esto solo funciona en todos los conjuntos, si la persona que llama del método condicional se vuelve a compilar.

Cuestiones relacionadas