valid - summary param name c#
¿Cuándo exactamente los tipos anulables lanzan excepciones? (4)
Esto es porque int? x = null;
int? x = null;
Básicamente, crea una instancia del tipo de valor System.Nullable<int>
, con un valor null
"interno" (puede verificarlo a través de la propiedad .HasVaue
). Cuando se invoca GetHashCode
, el Nullable<int>.GetHashCode
es el candidato candidato (ya que el método es virtual), ahora tenemos una instancia de Nullable<int>
y ejecutamos su método de instancia, perfecto.
Cuando se invoca GetType
, el método no es virtual, por lo que la instancia de Nullable<int>
se System.Object
primero en System.Object
, de acuerdo con el documento , y el valor encuadrado es null
, de ahí la NullReferenceException
.
Considere el siguiente código:
int? x = null;
Console.Write ("Hashcode: ");
Console.WriteLine(x.GetHashCode());
Console.Write("Type: ");
Console.WriteLine(x.GetType());
Cuando se ejecuta, escribe que Hashcode es 0
, pero falla con NullReferenceException
en un intento de determinar el tipo de x
. Sé que los métodos llamados en tipos anulables realmente son llamados en valores subyacentes, por lo que esperaba que el programa fallara durante x.GetHashCode()
.
Entonces, ¿cuál es la diferencia fundamental entre estos dos métodos y por qué no falla el primero de ellos?
La implementación de Nullable<T>.GetHashCode()
es la siguiente:
public override int GetHashCode()
{
if (!this.HasValue)
{
return 0;
}
return this.value.GetHashCode();
}
Entonces, cuando el valor es nulo, siempre obtendrá 0
.
x.GetType()
es igual que null.GetType()
que arrojará la Object reference not set to an instance of an object
Para aclarar la respuesta correcta de Danny Chen:
-
Nullable<T>
es un tipo de valor. El tipo de valor consta de un valor bool, que indica nulidad (falso significa nulo) y una T, el valor. - A diferencia de todos los demás tipos de valor, los tipos que
Nullable<T>
en una cajaNullable<T>
. Encajonan en una cajaT
o una referencia nula. - Un método implementado por un tipo de valor
S
se implementa como si tuviera un argumentoref S
invisible; Así es como se pasa esto. - Un método implementado por un tipo de referencia
C
se implementa como si hubiera un argumentoC
invisible; Así es como se pasa esto. - El caso interesante es un método virtual definido en una clase base de referencia y reemplazado por una estructura que hereda de la clase base.
Ahora tienes suficiente información para deducir lo que pasa. GetHashCode
es virtual y está anulado por Nullable<T>
modo que cuando lo llamas, lo llamas como si hubiera un ref Nullable<T>
invisible para this
. No pasa el boxeo.
GetType
no es virtual y, por lo tanto, no se puede anular y se define en el object
. Por lo tanto, espera un object
para this
. Cuando se llama a un Nullable<T>
el receptor debe estar encuadrado, y por lo tanto puede encasillar en nulo, y por lo tanto puede lanzar.
Si ((object)x).GetHashCode()
entonces ((object)x).GetHashCode()
una excepción.
Parece que GetHashCode tiene un cheque nulo. (Usado JetBrains para ver la definición)
public override int GetHashCode()
{
if (!this.hasValue)
return 0;
return this.value.GetHashCode();
}