valor - nullable property c#
¿Cómo funciona la adición a una cadena nula en C#? (4)
Me sorprendió ver un ejemplo de cadena inicializada a nula y luego tener algo agregado a ella en un entorno de producción. Simplemente olía mal.
Estaba seguro de que habría arrojado una excepción de objeto nulo, pero este ejemplo muy reducido también funciona:
string sample = null;
sample += "test";
// sample equals "test"
* Tenga en cuenta que el código original que encontré establece una propiedad de cadena como nula y se agrega a ella en otro lugar por lo que las respuestas que involucren al compilador que optimiza el nulo en tiempo de compilación son irrelevantes.
¿Alguien puede explicar por qué esto funciona sin error?
Seguir:
Basándome en la respuesta de Leppie, usé Reflector para ver qué hay dentro de string.Concat. Ahora es realmente obvio por qué ocurre esa conversión (sin magia en absoluto):
public static string Concat(string str0, string str1)
{
if (IsNullOrEmpty(str0))
{
if (IsNullOrEmpty(str1))
{
return Empty;
}
return str1;
}
if (IsNullOrEmpty(str1))
{
return str0;
}
int length = str0.Length;
string dest = FastAllocateString(length + str1.Length);
FillStringChecked(dest, 0, str0);
FillStringChecked(dest, length, str1);
return dest;
}
** Nota: la implementación específica que estaba investigando (en la biblioteca .Net de Microsoft) no se convierte en cadenas vacías como sugieren los estándares C # y la mayoría de las respuestas, pero usa algunas pruebas para atajar el proceso. El resultado final es el mismo que si lo hiciera, pero ahí lo tienes :)
Aquí es a lo que se compila su código para
string sample = null;
sample += "test";
se compila a este código IL:
.entrypoint
// Code size 16 (0x10)
.maxstack 2
.locals init ([0] string sample)
IL_0000: nop
IL_0001: ldnull
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: ldstr "test"
IL_0009: call string [mscorlib]System.String::Concat(string,
string)
IL_000e: stloc.0
IL_000f: ret
Y String.Concat
se encarga de la cadena NULL.
La cita relevante debe ser ECMA-334 §14.7.4:
Concatenación de cadenas:
string operator +(string x, string y); string operator +(string x, object y); string operator +(object x, string y);
El operador binario
+
realiza la concatenación de cadenas cuando uno o ambos operandos son de tipostring
. Si un operando de concatenación de cadenas esnull
, se sustituye una cadena vacía. De lo contrario, cualquier operando que no sea de cadena se convierte a su representación de cadena invocando el método virtual deToString
heredado de typeobject
. SiToString
devuelvenull
, se sustituye una cadena vacía.
el operador +
para cadenas es solo una abreviatura de string.Concat
que simplemente convierte argumentos null
en cadenas vacías antes de la concatenación.
Actualizar:
La versión generalizada de string.Concat:
public static string Concat(params string[] values)
{
int num = 0;
if (values == null)
{
throw new ArgumentNullException("values");
}
string[] array = new string[values.Length];
for (int i = 0; i < values.Length; i++)
{
string text = values[i];
array[i] = ((text == null) ? string.Empty : text);
num += array[i].Length;
if (num < 0)
{
throw new OutOfMemoryException();
}
}
return string.ConcatArray(array, num);
}
es porque
En las operaciones de concatenación de cadenas, el compilador de C # trata una cadena nula igual que una cadena vacía, pero no convierte el valor de la cadena nula original.
De Cómo: Concatenar cadenas múltiples (Guía de programación C #)
El operador binario + realiza la concatenación de cadenas cuando uno o ambos operandos son de tipo cadena. Si un operando de concatenación de cadenas es nulo, se sustituye una cadena vacía. De lo contrario, cualquier argumento que no sea cadena se convierte a su representación de cadena invocando el método virtual ToString heredado de tipo objeto. Si ToString devuelve null, se sustituye una cadena vacía.
Desde el operador adicional