ToString anulable ()

142

Veo en todas partes construcciones como:

int? myVar = null;
string test = myVar.HasValue ? myVar.Value.ToString() : string.Empty;

¿Por qué no usar simplemente:

string test = myVar.ToString();

¿No es exactamente lo mismo? Al menos Reflector dice que:

public override string ToString()
{
  if (!this.HasValue)
  {
    return "";
  }
  return this.value.ToString();
}

Entonces, ¿es correcto (la versión más corta) o me falta algo?

IamDeveloper
fuente
1
No he visto un código como este :)
tymtam

Respuestas:

112

Tienes toda la razón. También en esta pregunta , se sugiere la solución anterior, mientras que nadie se da cuenta de que ToString()ya da la respuesta correcta.

Tal vez el argumento para la solución más detallada es la legibilidad: cuando recurres ToString()a algo que se supone que es null, generalmente esperas un NullReferenceException, aunque aquí no se arroja.

Tomás Vana
fuente
21
En realidad, al menos dos personas se dieron cuenta: Eric Lippert y Johannes Rössel.
Jon Skeet
77
Si bien estoy seguro de que eso no es lo que querías decir, la referencia no es realmente nula aquí. Nullable <T> es un tipo de valor. Es por eso que las llamadas ToString()funcionan sin que NullReferenceExceptionse lancen.
Thorarin
2
Si esa fuera la mentalidad, esperarías .HasValuelanzar esa excepción.
Extragorey
Otra razón por la que las personas usan la versión detallada podría ser la paridad con expresiones como myNullableDateTime.HasValue ? myNullableDateTime.Value.ToString("d") : nulldonde necesita el objeto sin abrir para acceder al ToStringmétodo deseado . Por supuesto, también hay una solución más concisa para eso:$"{myNullableDateTime:d}"
Extragorey
14

Creo que muchas personas tienen tales controles porque no es un comportamiento natural de un objeto que pueda tener un valor nulo.

Andrew Bezzub
fuente
@Andrew, de acuerdo, porque la gente (como yo) piensa al principio que arrojará una excepción.
Nathan Koop
1
No tenía idea de que este era el comportamiento. Definitivamente habría pensado que cualquier construcción que devuelva verdadero para (x == nulo) también arrojaría una NullReferenceException si llama a x.ToString ().
Dan Bryant
5

No, tienes razón, la versión más corta es la misma que otras personas han hecho al respecto. El otro constructo que tiendo a usar mucho en lugar del ternario con valores nulos es el operador de fusión nula. que también te protege de los nulos. Para ToString () no es necesario (como señaló), pero para los valores int predeterminados (por ejemplo) funciona bien, por ejemplo:

int page = currentPage ?? 1;

que le permite hacer todas las operaciones de enteros en la página sin primero verificar explícitamente nulo y solicitar el valor en currentPage (¿dónde currentPage es un int? quizás pasado como un parámetro)

Pablo
fuente
5

Lo sé, mucho después de que fuera relevante, pero ... sospecho que se debe a tipos anulables como int? El método .ToString () no le permite utilizar cadenas de formato. Consulte ¿Cómo puedo formatear un DateTime anulable con ToString ()? . Quizás en el código original, había una cadena de formato en .ToString (), o tal vez el codificador olvidó que .ToString () sin la cadena de formato todavía estaba disponible en tipos anulables.

outis nihil
fuente
3

puede ser solo para seguir el patrón? o no conocen el backend. tienes razón el código es exactamente el mismo. incluso puedes hacer:

int? i = null;
i.ToString(); //No NullReferenceException
Andrey
fuente
Es posible que deba tomar la ruta larga si ToString () debe ser de cultura invariable, ya que los valores anulables no lo tienen en su menú.
Ε Г И І И О
1

int?es el azúcar de sintaxis que simplifica la declaración de la variable anulable. Es lo mismo que Nullable<int>.

Entonces, si echa un vistazo a la implementación del ToString()método para Nullable<T> (ver más abajo) , puede notar que devuelve una cadena vacía en caso de que no tenga valor.

public struct Nullable<T> where T : struct
{
    public override string ToString()
    {
      if (!this.hasValue)
        return "";
      return this.value.ToString();
    }
}

Lo que dice MSDN:

Método Nullable.ToString

Devuelve la representación de texto del valor del objeto actual Nullable si la propiedad HasValue es verdadera, o una cadena vacía ("") si la propiedad HasValue es falsa.

Entonces, el siguiente código imprimirá una cadena vacía en la consola en lugar de lanzar una ArgumentNullExceptionexcepción.

static void Main(string[] args)
{
    int? a = null;
    Console.WriteLine(a.ToString()); // Prints empty string to console.
}
Aliaksei Maniuk
fuente