sistema referencia que objeto marco instancia fisica establecida error ejercicios como c# null nullable value-type reference-type

referencia - system.nullreferenceexception c#



Tipos de referencia vs tipos anulables ToString() (6)

¿Podría alguien, por favor, ser lo suficientemente amable para explicar por qué llamar a ToString() en un tipo de referencia vacío causa una excepción (que en mi opinión tiene mucho sentido, no puede invocar un método en nada!) Pero llamar a ToString() en un Nullable(Of T) vacío Nullable(Of T) devuelve String.Empty ? Esto fue una gran sorpresa para mí ya que asumí que el comportamiento sería consistente en todos los tipos.

Nullable<Guid> value = null; Stock stock = null; string result = value.ToString(); //Returns empty string string result1 = stock.ToString(); //Causes a NullReferenceException


Es un poco complicado con tipos anulables. Cuando lo establece en null en realidad no es null porque no es un tipo de referencia (es un tipo de valor). Cuando inicializa dicha variable con null , crea una nueva instancia de estructura donde la propiedad HasValue es false y su Value es null , por lo que cuando llama ToString método ToString funciona bien en la instancia de estructura.


La excepción default(object).ToString() al llamar a default(object).ToString() se llama NullReferenceException por una razón, está llamando a un método en una referencia nula. default(int?) por otro lado, no es una referencia nula, porque no es una referencia; es un tipo de valor con un valor que es equivalente a nulo.

El gran punto práctico es que si esto se hiciera, lo siguiente fallaría:

default(int?).HasValue // should return false, or throw an exception?

También arruinaría la forma en que tenemos cierta capacidad para mezclar nullables y no nulables:

((int?)null).Equals(1) // should return false, or throw an exception?

Y lo siguiente se vuelve completamente inútil:

default(int?).GetValueOrDefault(-1);

Podríamos deshacernos de HasValue y forzar la comparación con null, pero luego, si la anulación de la igualdad del tipo de valor que se hace anulable puede ser verdadera en comparación con null en algunos casos. Puede que no sea una gran idea, pero se puede hacer y el lenguaje tiene que hacer frente.

Recordemos por qué se introducen los tipos anulables. La posibilidad de que un tipo de referencia pueda ser nulo, es inherente al concepto de tipos de referencia a menos que se haga un esfuerzo para imponer la no nulabilidad: los tipos de referencia son tipos que se refieren a algo, y eso implica la posibilidad de que uno no se refiera a nada, lo cual Llamamos nulo .

Si bien es una molestia en muchos casos, podemos hacer uso de esto en una variedad de casos, como representar "valor desconocido", "ningún valor válido", etc. (podemos usarlo para lo que nulo significa en bases de datos, por ejemplo) .

En este punto, le hemos dado un significado nulo a un contexto dado, más allá del simple hecho de que una referencia dada no se refiere a ningún objeto.

Como esto es útil, podríamos querer establecer un int o DateTime en nulo, pero no podemos porque no son tipos que se refieren a otra cosa, y por lo tanto no podemos estar en un estado de no referirnos a nada. más que yo como mamífero puedo perder mis plumas.

Los tipos anulables introducidos con 2.0 nos dan una forma de tipos de valor que puede tener el nulo semántico, a través de un mecanismo diferente al de los tipos de referencia. La mayoría de esto podría codificarse si no existiera, pero las reglas especiales de boxeo y promoción permiten un uso más sensato del operador y el boxeo.

Bueno. Ahora consideremos por qué las NullReferenceExceptions ocurren en primer lugar. Dos son inevitables, y una fue una decisión de diseño en C # (y no se aplica a todo .NET).

  1. Intenta llamar a un método o propiedad virtual, o acceder a un campo en una referencia nula. Esto tiene que fallar, porque no hay manera de buscar a qué anulación se debe llamar, y no hay tal campo.
  2. Llama a un método o propiedad no virtual en una referencia nula que a su vez llama a un método o propiedad virtual, o accede a un campo. Obviamente, esta es una variante del punto uno, pero la decisión de diseño que tenemos a continuación tiene la ventaja de garantizar que esto falla al principio, en lugar de a la mitad (lo que podría ser confuso y tener efectos secundarios a largo plazo) .
  3. Llama a un método o propiedad no virtual en una referencia nula que no llama a un método o propiedad virtual, o accede a un campo. No hay una razón intrínseca por la que no se debe permitir esto, y algunos idiomas lo permiten, pero en C # decidieron usar callvirt lugar de call para forzar una NullReferenceException por coherencia (no puedo decir que esté de acuerdo, pero ya está) .

Ninguno de estos casos se aplica de ninguna manera a un tipo de valor anulable. Es imposible poner un tipo de valor anulable en una condición en la que no hay forma de saber a qué campo o método anular acceso. El concepto completo de NullReferenceException simplemente no tiene sentido aquí.

En general, no lanzar una NullReferenceException es coherente con los otros tipos, tipos a través de él si y solo si se usa una referencia nula.

Tenga en cuenta que hay un caso en el que se invoca a un tipo nulo de null lanzamientos, lo hace con GetType() , porque GetType() no es virtual, y cuando se llama en un tipo de valor siempre hay un boxeo implícito. Esto es cierto para otros tipos de valores, así que:

(1).GetType()

se trata como:

((object)1).GetType()

Pero en el caso de los tipos anulables, el boxeo convierte a aquellos con un valor de HasValue falso en nulo, y por lo tanto:

default(int?).GetType()

siendo tratado como:

((object)default(int?)).GetType()

lo que hace que se GetType() a GetType() en un objeto nulo y, por lo tanto, se lance.

Esto incidentalmente nos lleva a por qué no fingir NullReferenceType fue la decisión de diseño más sensata: las personas que necesitan ese comportamiento siempre pueden encasillar. Si lo desea, utilice ((object)myNullableValue).GetString() para que no sea necesario que el lenguaje lo trate como un caso especial para forzar la excepción.

EDITAR

Oh, olvidé mencionar la mecánica detrás de NullReferenceException .

La prueba para NullReferenceException es muy barata, ya que en su mayoría simplemente ignora el problema y luego detecta la excepción del sistema operativo si ocurre. En otras palabras, no hay prueba .

Consulte ¿Qué es la implementación de CLR detrás de generar / generar una excepción de referencia nula? y observe cómo nada de eso funcionaría con tipos de valores que puedan contener nulos.


Nullable es un tipo de valor y la asignación a null hace que se inicialice con Value=null y HasValue=false .

Además, Nullable.ToString () se implementa de la siguiente manera:

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

Así que lo que estás viendo es lo esperado.


Según las observaciones de MSDN

Guid.ToSTring() Devuelve una representación de cadena del valor de esta instancia de Guid, de acuerdo con el especificador de formato proporcionado.

De acuerdo con los comentarios de MSDN en Nullable

Se dice que un tipo es anulable si se le puede asignar un valor o se le puede asignar un valor nulo, lo que significa que el tipo no tiene valor alguno. En consecuencia, un tipo anulable puede expresar un valor, o que no existe ningún valor. Por ejemplo, un tipo de referencia como String es anulable, mientras que un tipo de valor como Int32 no lo es. Un tipo de valor no puede ser anulable porque tiene la capacidad suficiente para expresar solo los valores apropiados para ese tipo; no tiene la capacidad adicional requerida para expresar un valor de nulo.


Si investiga la definición de Nullable<> , hay una definición de anulación de ToString. En esta función, ToString se reemplaza para devolver String.Empty.

// Summary: // Returns the text representation of the value of the current System.Nullable<T> // object. // // Returns: // The text representation of the value of the current System.Nullable<T> object // if the System.Nullable<T>.HasValue property is true, or an empty string ("") // if the System.Nullable<T>.HasValue property is false. public override string ToString();

Por otro lado, Stock es una clase personalizada, que supongo que ToString no está anulada. Por lo tanto, devuelve NullReferenceException ya que utiliza el comportamiento predeterminado.


Nullable<T> es en realidad una struct que tiene algún soporte de compilación y soporte de implementación para comportarse como un null sin ser realmente null .

Lo que está viendo es la colisión entre la implementación que le permite tratarlo de forma natural como null como lo haría con cualquier otro tipo de referencia, pero permitiendo que se produzca la llamada al método porque Nullable<T> no es realmente nulo, el valor en su interior es nulo.

Visualmente parece que no debería funcionar, esto es simplemente porque no puedes ver lo que se hace en segundo plano por ti.

Se pueden ver otros trucos visuales de este tipo cuando se llama a un método de extensión en un tipo de referencia nula ... la llamada funciona (en contra de la expectativa visual) porque bajo el capó se resuelve en una llamada de método estático que pasa su instancia nula como parámetro.

¿Cómo funciona un tipo Nullable <T> detrás de escena?