2012-09-13 103 views
11

Quiero comprobar si una variable se inicializa en tiempo de ejecución, programáticamente. Para que las razones de esto sean menos misteriosas, consulte el siguiente código incompleto:C# - comprobando si se inicializa una variable

string s; 

if (someCondition) s = someValue; 
if (someOtherCondition) s = someOtherValue; 

bool sIsUninitialized = /* assign value correctly */; 

if (!sIsUninitialized) Console.WriteLine(s) else throw new Exception("Please initialize s."); 

Y complete el bit correspondiente.

Una solución hacky es inicializar s con un valor por defecto:

string s = "zanzibar"; 

Y a continuación, comprobar si ha cambiado:

bool sIsUninitialized = s == "zanzibar"; 

Sin embargo, lo que si someValue o someOtherValue resultan ser "Zanzíbar" ¿también? Entonces tengo un error. ¿Alguna mejor manera?

+5

'string.IsNullOrEmpty (s)' – Shmiddty

+7

Esto en realidad ni siquiera compilará. Las variables deben ser inicializadas. Simplemente inícielo a nulo o cadena. Vacío. – McGarnagle

+0

¿Qué sucede si la variable se inicializa con otro hilo? ¿Se siente cómodo configurando el controlador de memoria para generar una excepción en el acceso de escritura? – HABO

Respuesta

12

El código ni siquiera se compilará si el compilador sabe que una variable no se ha inicializado.

string s; 
if (condition) s = "test"; 
// compiler error here: use of unassigned local variable 's' 
if (s == null) Console.Writeline("uninitialized"); 

En otros casos se puede utilizar la palabra clave default si una variable no se haya inicializado. Por ejemplo, en el siguiente caso:

class X 
{ 
    private string s; 
    public void Y() 
    { 
     Console.WriteLine(s == default(string)); // this evaluates to true 
    } 
} 

Los documentation estados que predeterminado (T) dará null para los tipos de referencia, y 0 para los tipos de valor. Como se señaló en los comentarios, esto es realmente lo mismo que buscar nulo.


Todo esto oculta el hecho de que realmente debería inicializar variables, a null o lo que sea, cuando se declaran en primer lugar.

+4

¿No es 's == default (string)' una forma elegante de decir 's == null'? – dasblinkenlight

+1

@dasblinkenlight, bueno, sí, básicamente, pero creo que hace que la intención sea un poco más explícita. – McGarnagle

+10

@dbaseman, no estoy de acuerdo. Ofusca la conocida comprensión de lo que es 'null'. –

2

Puede mantener una bandera independiente que indica que la cadena se ha inicializado:

string s = null; 
bool init = false; 
if (conditionOne) { 
    s = someValueOne; 
    init = true; 
} 
if (conditionTwo) { 
    s = someValueTwo; 
    init = true; 
} 
if (!init) { 
    ... 
} 

Esto se hará cargo de situaciones en las que se asigna s, incluyendo los casos en los que se asigna null, cadena vacía, o "zanzibar".

Otra solución es hacer una cadena estática para denotar el valor "no inicializado", y usar Object.ReferenceEquals en lugar de == para verificar si ha cambiado. Sin embargo, el enfoque de variable bool expresa su intención mucho más explícitamente.

+0

¿Por qué introducir la bandera y no simplemente comparar 's' contra' null'? –

+5

@KirkWoll Esa es una gran pregunta, aunque intenté responderla en la respuesta: porque 'someValueOne' o' someValueTwo' podría ser legítimamente 'null'. (Actualización: aparentemente, al OP no le importa :) – dasblinkenlight

+0

Lo suficiente, no leí tu respuesta lo suficientemente bien. ;) –

0

que recoger valores de inicialización que no se pueden utilizar, los valores típicos incluyen String.Empty, null, -1, y un generador de cadena aleatoria de 256 caracteres.

+2

'string.Empty' =' "" '. No es necesario usar una alternativa tres veces más detallada. Después de todo, no usamos cosas como 'Int32.Zero'. –

+0

Prefiero String.Empty porque no se puede confundir con '' ''. Es más fácil de leer para mí. –

+2

No debe confundirse con '" "'. De Verdad. Es una parte integral de cualquier lenguaje de programación. –

3

Sólo asignarle null por defecto, no un valor de cadena

+0

¿Qué pasa si 'null' es un valor válido para que la cadena se asigne en una de las sentencias' if'? – Servy

+0

@Servy Luego defina una constante que represente su valor no nulo, no inicializado, p. Ej. 'const string UninitializedString =" zanzibar ";' –

+1

@PeterGluck Entonces ese valor constante ahora se vuelve "inválido", y lo que es peor, haría que la depuración sea extraordinariamente difícil porque si algún método devuelve eso determina por qué no funciona en absoluto causaría todo tipo de dolores de cabeza. – Servy

8

con C# 2.0, usted tiene el operador aceptan valores NULL que le permite establecer un valor inicial de cero para los tipos de valor hasta ahora, teniendo en cuenta cosas tales como:

int? x = null; 

if (x.HasValue) 
{ 
    Console.WriteLine("Value for x: " + num.Value); 
} 

Que rendimientos: "Value for x: Null".

+2

Esto no es aplicable a cadenas, porque ya es un tipo de referencia. – dasblinkenlight

+0

La frase introductoria del OP decía "Quiero verificar si una variable se inicializa en tiempo de ejecución". El tipo era una cadena solo en lo que el OP indicaba que era su "código incompleto" usado para un ejemplo. –

+2

No use literales booleanos en los controles, escriba 'if (x.HasValue)'. Los literales booleanos solo son significativos en las inicializaciones (o cuando se pasan como parámetros), en ningún otro lugar. –

3

Aquí hay una manera:

string s; 
if (someCondition) { s = someValue; } 
else if (someOtherCondition) { s = someOtherValue; } 
else { throw new Exception("Please initialize s."); } 

Console.WriteLine(s) 

Esto podría ser preferible para comprobar si la cadena es nula, porque tal vez someValue es un método que a veces puede devolver null. En otras palabras, quizás nulo es un valor legítimo para inicializar la cadena.

Personalmente me gusta más que una bandera isInitialized. ¿Por qué introducir una variable de indicador adicional a menos que sea necesario? No creo que sea más legible.

+0

Obviamente 'someValue' no es un método o sería' SomeValue() ', pero me refiero a" en el caso real (no simplificado) ". Todavía podría ser 'nulo' en cualquier caso. –

-1

En general, asigne el valor predeterminado a null o String.Empty. Para situaciones donde no se puede utilizar esos valores "vacías", definir una constante para representar a su valor inicializado específica de la aplicación:

const string UninitializedString = "zanzibar"; 

después hacer referencia a ese valor cada vez que desee inicializar o prueba para la inicialización:

string foo = UnininitializedString; 
if (foo == UninitiaizedString) { 
    // Do something 
} 

Recuerde que las cadenas son constantes inmutables en C#, por lo que en realidad solo hay una instancia de UninitializedString (por lo que la comparación funciona).

+1

Esta es una receta para el desastre. En algún momento podría terminar con una asignación legítima a ese valor "no inicializado", causando todo tipo de confusión para los programadores que necesitan tratar de determinar por qué no está funcionando. – Servy

+0

@Servy No es así. Esa es exactamente la razón por la que utiliza una constante con nombre en lugar de rociar una cadena "desnuda" en todo el código. La constante se puede cambiar según sea necesario en el futuro. Y tenga en cuenta que dije que su primera opción es usar 'null' o' String.Empty'. De hecho, 'const string UninitializedString = String.Empty;' sería mi primera opción. –

+1

En primer lugar, no se debe rociar una cadena "desnuda" en todo el código. Utiliza una solución como [ésta] (http://stackoverflow.com/a/12414058/1159478) que nunca usa ningún valor para representar un "valor no inicializado". Que puedas cambiarlo (en tiempo de compilación) ni siquiera mitiga significativamente los peligros aquí. Si la cadena se puede basar en la entrada del usuario, no tiene idea en tiempo de compilación de lo que el usuario puede elegir; no importa lo que elijas, podría ser incorrecto. De hecho, no es tan raro tener una asignación válida para 'null' o una cadena vacía, por lo que usar eso no ayudará. – Servy

Cuestiones relacionadas