Inicialización de cadena predeterminada: NULL o Empty?

Siempre he inicializado mis cadenas a NULL, con el pensamiento de que NULL significa la ausencia de un valor y “” o String.Empty es un valor válido. Recientemente he visto más ejemplos de código donde String.Empty se considera el valor predeterminado o no representa ningún valor. Esto me parece extraño, con los tipos de nulos nuevos agregados en c # parece que estamos retrocediendo con las cadenas al no usar NULL para representar ‘Sin valor’.

¿Qué usas como inicializador predeterminado y por qué?

Editar: Basado en las respuestas, mis pensamientos posteriores

  1. Evitar el manejo de errores Si el valor no debe ser nulo, ¿por qué se estableció en NULL en primer lugar? Quizás sería mejor identificar el error en el lugar donde ocurre en lugar de cubrirlo en el rest de la base de código.

  2. Evitar las comprobaciones nulas Si está cansado de hacer comprobaciones nulas en el código, ¿no sería mejor resumir las comprobaciones nulas? Quizás envuelva (o extienda!) Los métodos de cadena para hacer que NULL seguro. ¿Qué sucede si constantemente utiliza String.Empty y ocurre que un nulo funciona en el sistema, ¿comienza a agregar cheques NULL todos modos?

No puedo evitar volver a la opinión de que es la pereza. Cualquier DBA te daría una bofetada de nueve maneras si usabas ” en lugar de null en su base de datos. Creo que los mismos principios se aplican en la progtwigción y debería haber alguien que String.Empty que String.Empty que usan String.Empty lugar de NULL para no representar ningún valor.

preguntas relacionadas

  • En C #, ¿debería usar string.Empty o String.Empty o “”?
  • Cuál es la diferencia entre String.Empty y “”
  • ¿Cadena vacía o nula para no representar datos en la columna de la tabla?

+1 para distinguir entre “vacío” y NULO. Estoy de acuerdo en que “vacío” debe significar “válido, pero en blanco” y “NULO” debe significar “inválido”.

Así que respondería a tu pregunta de esta manera:

vacío cuando quiero un valor predeterminado válido que puede o no modificarse, por ejemplo, el segundo nombre de un usuario.

NULL cuando es un error si el código resultante no establece el valor explícitamente.

De acuerdo con MSDN :

Al inicializar cadenas con el valor Empty lugar de null , puede reducir las posibilidades de que ocurra una NullReferenceException .

Sin IsNullOrEmpty() usar siempre IsNullOrEmpty() es una buena práctica.

¿Por qué quieres que tu cadena sea inicializada en absoluto? No tiene que inicializar una variable cuando declara una, e IMO, solo debe hacerlo cuando el valor que está asignando es válido en el contexto del bloque de código.

Veo esto mucho:

 string name = null; // or String.Empty if (condition) { name = "foo"; } else { name = "bar"; } return name; 

No inicializar a nulo sería igual de efectivo. Además, lo más frecuente es que desee asignar un valor. Al inicializar a nulo, puede perder rutas de código que no asignan un valor. Al igual que:

 string name = null; // or String.Empty if (condition) { name = "foo"; } else if (othercondition) { name = "bar"; } return name; //returns null when condition and othercondition are false 

Cuando no se inicializa a nulo, el comstackdor generará un error que indica que no todas las rutas de código asignan un valor. Por supuesto, este es un ejemplo muy simple …

Matthijs

Para la mayoría del software que no es realmente un software de procesamiento de cadenas, la lógica del progtwig no debe depender del contenido de las variables de cadena. Cada vez que veo algo como esto en un progtwig:

 if (s == "value") 

Tengo un mal presentimiento. ¿Por qué hay una cadena literal en este método? ¿Qué es la configuración s ? ¿Sabe que la lógica depende del valor de la cadena? ¿Sabe que tiene que ser minúscula para trabajar? ¿Debo arreglar esto al cambiarlo para usar String.Compare ? ¿Debería crear un Enum y analizarlo?

Desde esta perspectiva, uno llega a una filosofía de código que es bastante simple: evite examinar el contenido de una cuerda siempre que sea posible. Comparar una cadena con String.Empty es realmente solo un caso especial de compararlo con un literal: es algo que debes evitar hacer a menos que realmente tengas que hacerlo.

Sabiendo esto, no parpadeo cuando veo algo como esto en nuestra base de códigos:

 string msg = Validate(item); if (msg != null) { DisplayErrorMessage(msg); return; } 

Sé que Validate nunca devolvería String.Empty , porque escribimos un código mejor que eso.

Por supuesto, el rest del mundo no funciona así. Cuando su progtwig trata con la entrada del usuario, bases de datos, archivos, etc., debe dar cuenta de otras filosofías. Ahí, es el trabajo de tu código imponer orden en el caos. Parte de ese orden es saber cuándo una cadena vacía debería significar String.Empty y cuándo debería significar null .

(Solo para asegurarme de que no estaba hablando de mi trasero, busqué en nuestra base de código `String.IsNullOrEmpty ‘. Todas las 54 apariciones de esta son en métodos que procesan la entrada del usuario, devuelven valores de scripts Python, examinan valores recuperados de API externas, etc.)

Depende.

¿Necesita poder saber si falta el valor (es posible que no esté definido)?

¿La cadena vacía es un valor válido para el uso de esa cadena?

Si respondió “sí” a ambos, querrá usar null. De lo contrario, no puede distinguir entre “sin valor” y “cadena vacía”.

Si no necesita saber si no hay ningún valor, entonces la cadena vacía probablemente sea más segura, ya que le permite omitir las comprobaciones nulas donde sea que la use.

Esto es realmente un gran agujero en el lenguaje C #. No hay forma de definir una cadena que no puede ser nula. Esto causa problemas tan simples como el que está describiendo, lo que obliga a los progtwigdores a tomar una decisión que no deberían tomar, ya que en muchos casos NULL y String.Empty significan lo mismo. Eso, a su vez, puede obligar a otros progtwigdores a manejar NULL y String.Empty, lo cual es molesto.

Un problema mayor es que las bases de datos le permiten definir campos que se correlacionan con una cadena C #, pero los campos de la base de datos se pueden definir como NOT NULL. Por lo tanto, no hay forma de representar con precisión, por ejemplo, un campo varchar (100) NOT NULL en SQL Server utilizando un tipo C #.

Otros idiomas, como Spec #, permiten esto.

En mi opinión, la incapacidad de C # para definir una cadena que no permita el nulo es tan mala como su incapacidad previa para definir un int que permita el nulo.

Para responder completamente a su pregunta: siempre utilizo una cadena vacía para la inicialización predeterminada porque es más similar a cómo funcionan los tipos de datos de la base de datos. (Editar: Esta afirmación no era clara. Debe decir “Utilizo una cadena vacía para la inicialización predeterminada cuando NULL es un estado superfluo, del mismo modo que configuré una columna de base de datos como NOT NULL si NULL sería un estado superfluo. , muchas de mis columnas DB están configuradas como NOT NULL, así que cuando las coloque en una cadena C #, la cadena estará vacía o tendrá un valor, pero nunca será NULL. En otras palabras, solo inicializo una cadena en NULL si null tiene un significado que es distinto del significado de String.Empty, y considero que ese caso es menos que común (pero las personas aquí han dado ejemplos legítimos de este caso). “)

Parece que este es un caso especial del http://en.wikipedia.org/wiki/Null_Object_pattern

Lo ajusto a “” o nulo – Siempre lo compruebo usando String.IsNullOrEmpty, por lo que está bien.

Pero el friki interior en mí dice que debería establecerlo como nulo antes de tener un valor adecuado para eso …

Siempre declaro cadena con string.empty;

¿Es posible que esta sea una técnica para evitar errores (aconsejable o no …)? Dado que “” sigue siendo una cadena, ¿podría llamar a las funciones de cadena que darían lugar a una excepción si fuera NULO?

Siempre los inicializo como NULL .

Siempre uso string.IsNullOrEmpty(someString) para verificar su valor.

Sencillo.

Depende de la situación. En la mayoría de los casos, uso String.Empty porque no quiero hacer comprobaciones nulas cada vez que bash usar una cadena. Hace que el código sea mucho más simple y es menos probable que presente lockings NullReferenceException no deseados.

Solo configuro la cadena como nula cuando necesito saber si se ha configurado o no y donde una cadena vacía es algo válido para configurarla. En la práctica, encuentro que estas situaciones son raras.

Una cadena vacía es un valor (una pieza de texto que, casualmente, no contiene ninguna letra). Nulo significa sin valor.

Inicializo las variables a nulo cuando deseo indicar que no señalan ni contienen valores reales, cuando la intención es sin valor.

Reiterando la respuesta de Tomalak, tenga en cuenta que cuando asigna una variable de cadena a un valor inicial de nulo, su variable ya no es un objeto de cadena; lo mismo con cualquier objeto en C #. Entonces, si intenta acceder a cualquier método o propiedad para su variable y está asumiendo que es un objeto de cadena, obtendrá la excepción NullReferenceException.

Null solo debe usarse en casos donde un valor es opcional. Si el valor no es opcional (como ‘Nombre’ o ‘Dirección’), entonces el valor nunca debe ser nulo. Esto se aplica tanto a las bases de datos como a las POCO y la interfaz de usuario. Nulo significa “este valor es opcional y actualmente está ausente”.

Si su campo no es opcional, entonces debe inicializarlo como la cadena vacía. Inicializarlo como nulo colocaría su objeto en un estado inválido (no válido por su propio modelo de datos).

Personalmente, preferiría que las cadenas no se puedan anular de forma predeterminada, sino que solo se puedan anular si declaramos una “cadena”. Aunque quizás esto no sea factible o lógico en un nivel más profundo; no es seguro.

Las cadenas no son tipos de valores, y nunca lo serán 😉

Creo que no hay ninguna razón para no usar null para un valor no asignado (o en este lugar en un flujo de progtwig que no ocurre). Si quieres distinguir, hay == nulo. Si solo quiere comprobar un valor determinado y no le importa si es nulo o algo diferente, String.Equals (“XXX”, MyStringVar) no tiene ningún problema.