2011-11-22 21 views
54

¿C tiene un noConditional (!Conditional, NotConditional, Conditional(!)) atributo?C#! Atributo condicional?


sé C# tiene una Conditional attribute:

[Conditional("ShowDebugString")] 
public static void ShowDebugString(string s) 
{ 
    ... 
} 

lo que equivale a:

public static void ShowDebugString(string s) 
{ 
#if ShowDebugString 
    ... 
#endif 
} 

Pero en este caso quiero que el inversa comportamiento (que tiene Específicamente inhabilitar):

public static void ShowDebugString(string s) 
{ 
#if !RemoveSDS 
    ... 
#endif 
} 

Lo cual me lleva a tratar:

[!Conditional("RemoveSDS")] 
public static void ShowDebugString(string s) 
{ 
    ... 
} 

que no compilar. Y:

[Conditional("!RemoveSDS")] 
public static void ShowDebugString(string s) 
{ 
    ... 
} 

que no se compila. Y:

[NotConditional("RemoveSDS")] 
public static void ShowDebugString(string s) 
{ 
    ... 
} 

que no se compila porque es solo una ilusión.

Not true, but true enough. Don't make me bring back the Nitpicker's Corner.

+5

Nop. Tenga en cuenta que '[Conditional (...)]' no es equivalente a eso; también elimina los sitios de llamadas. – SLaks

+0

@SLaks: Estaba escribiendo una respuesta que incluye ese mismo punto :) –

Respuesta

45

primer lugar, que tiene el atributo de Conditional es no equivalente a tener #if en lugar del método. Considere lo siguiente:

ShowDebugString(MethodThatTakesAges()); 

con el comportamiento real de ConditionalAttribute, MethodThatTakesAges no se consiga llamar - la llamada completa incluyendo la evaluación argumento se retira del compilador.

Por supuesto, el otro punto es que depende de los símbolos del preprocesador en tiempo de compilación en el momento de la compilación de la persona que llama , no del método :)

Pero no, no creo hay algo que hace lo que quieres aquí. Acabo de consultar la sección de especificaciones de C# 17.4.2, que trata de los métodos condicionales y las clases de atributos condicionales, y no hay nada allí que sugiera que exista tal mecanismo.

+0

Lo más cerca que puede obtener limpiamente es la solución de SLAKS a continuación. – NoxMortem

0

La biblioteca estándar del marco NET referencia anotada no indica ninguna. ¡Así que me temo que tendrás que hacer tu propio!

+0

Eso no es posible. – SLaks

4
#ifndef ShowDebugString 
#define RemoveSDS 
#endif 

?

editar: Para obtener más aclaraciones. Si se define ShowDebugString, se llamará Conditional["ShowDebugString"]. Si ShowDebugString no está definido, se llamará Conditional["RemoveSDS"].

+1

Sin embargo, esto debería estar en el código * de llamada - en cada archivo donde se requirió la función. Es significativamente diferente a lo solicitado, IMO. –

+0

@JonSkeet +1 por mencionar el valor de una solución global, en lugar de requerir que todos cambien todos los códigos existentes (http://stackoverflow.com/questions/244246/c-alias-a-clase-nombre) –

+0

La mejor solución es probablemente agregue una nueva definición en el nivel de proyecto que tenga el valor correcto/esperado para cada configuración de compilación. – James

34

No.

su lugar, puede escribir

#if !ShowDebugString 
[Conditional("FALSE")] 
#endif 

Tenga en cuenta que a diferencia de [Conditional], esto será determinado por la presencia del símbolo en su montaje, no en la asamblea de la persona que llama.

+0

Esta es en realidad la mejor solución, sin embargo, recomiendo usar un hash aleatorio largo en lugar de FALSE, que podría establecerse en algún ensamblaje. – NoxMortem

8

Simplemente agregando mis 2 centavos, tres años en la línea :-) ... Utilizo un método [Conditional("DEBUG")] para establecer una propiedad IsDebugMode para verificar el reverso. Hacky, pero funciona:

private bool _isDebugMode = false; 
public bool IsDebugMode 
{ 
    get 
    { 
     CheckDebugMode(); 
     return _isDebugMode; 
    } 
} 

[Conditional("DEBUG")] 
private void CheckDebugMode() 
{ 
    _isDebugMode = true; 
} 

private void DisplaySplashScreen() 
{ 
    if (IsDebugMode) return; 

    var splashScreenViewModel = new SplashScreenVM(500) 
    { 
     Header = "MyCompany Deals", 
     Title = "Main Menu Test", 
     LoadingMessage = "Creating Repositories...", 
     VersionString = string.Format("v{0}.{1}.{2}", 
      GlobalInfo.Version_Major, GlobalInfo.Version_Minor, GlobalInfo.Version_Build) 
    }; 

    SplashScreenFactory.CreateSplashScreen(splashScreenViewModel); 
} 
+0

¿Por qué harías esto? ¿Por qué no usar algo como '#if si DEBUG devuelve true? #else return false; # endif'? –

+2

Eche un vistazo a esta discusión en profundidad sobre los méritos del uso de etiquetas pragma frente a atributos condicionales. Es demasiado para explicar en un comentario: http://stackoverflow.com/questions/3788605/if-debug-vs-conditionaldebug – Heliac

+0

Iba a escribir algo como esto, me alegra que lo hayas hecho por mí, pero es extraño que esta respuesta es tan abajo. No creo que funcione si este código está en un ensamblaje diferente, porque la decisión de si se llama o no al "CheckDebugMode" se realiza cuando la ensambla, no cuando la llama. En este sentido, es bastante similar a usar un #if para verificarlo. –

14

Es cierto que no podemos 'NO' ConditionalAttribute, pero podemos 'NO' la condición que se presenta a continuación.

// at the begining of the code before uses 
#if DUMMY 
#undef NOT_DUMMY 
#else 
#define NOT_DUMMY 
#endif 

// somewhere in class 
[Conditional("NOT_DUMMY")] 
public static void ShowDebugStringNOTDUMMY(string s) 
{ 
    Debug.Print("ShowDebugStringNOTDUMMY"); 
} 


[Conditional("DUMMY")] 
public static void ShowDebugStringDUMMY(string s) 
{ 
    Debug.Print("ShowDebugStringDUMMY"); 
} 

esperanza esto ayuda a resolver su problema;)

+2

-1 Buen intento, pero esto no siempre funcionará, ya que esto no depende de los símbolos del preprocesador en tiempo de compilación de la persona que llama (especialmente si la persona que llama está en otro ensamblaje u otro módulo dentro del mismo ensamblaje). – Kryptos

+0

Sí, depende del contexto del compilador de la persona que llama para todas las asambleas en el momento de la compilación (la condición #if debe estar en el contexto de la persona que llama como lo indica el estándar C#). Nunca dije que funcionaría o no si ponemos la condición #if en otro ensamblaje, y esa no era la pregunta de OP. Entonces, si puedo preguntar por qué voto abajo? – SoLaR

Cuestiones relacionadas