valor - validar fecha null en c#
¿Por qué.ToString() en una cadena nula causa un error nulo, cuando.ToString() funciona bien en una int nullable con valor nulo? (8)
selectedItem
tiene dos campos:
-
int? _cost
-
string _serialNumber
En este ejemplo, _cost
y _serialNumber
de selectedItem
son AMBOS nulos. Estoy leyendo los campos de selectedItem
través de sus propiedades, y completando cuadros de texto con sus valores, cuando ...
TextBox1.Text = selectedItem.Cost.ToString(); //no error
TextBox2.Text = selectedItem.SerialNumber.ToString(); //error
Entiendo que SerialNumber.ToString()
es redundante (porque ya es una cadena), pero no entiendo por qué esto causa esta excepción:
Objeto nullable debe tener un valor.
-
int? _cost
int? _cost
es anulable, y no tiene un valor, sin embargo, no me da la excepción. -
string _serialNumber
es anulable, y no tiene un valor, sin embargo , me da la excepción.
Esta question toca, el tipo esencialmente está preguntando lo mismo, pero no hay una respuesta designada, y tampoco explica por qué una int
nullable? Por ejemplo, ¿puedo usar .ToString()
en un int nullable pero no en una cadena nula?
Como el null
del tipo de string
realmente no apunta a nada, no hay ningún objeto en la memoria.
Pero int?
type (nullable) incluso con el valor establecido en null
aún apunta a algún objeto.
Si lees "CLR via C #" de Jeffrey Richter, descubrirás que los tipos con anulación son solo clases de fachada para tipos comunes con algunas lógicas encapsuladas para hacer que trabajar con DB null sea más conveniente.
Verifique msdn para aprender sobre tipos anulables.
El Nullable es en realidad una estructura que expone dos propiedades: HasValue y Value. Si haces esto, obtendrás tu error:
int? i = null;
i.Value.ToString()
Para comprobar si su int? tiene un valor que puede acceder a i.HasValue
El motivo es simple int?
o Nullable<int>
es una estructura o un tipo de valor , nunca puede ser nulo .
Entonces, ¿qué sucede cuando lo hacemos?
int? _cost = null;
_cost
tendrá dos campos Value
y HasValue
, cuando asignamos null
a _cost
su indicador HasValue
se establecerá en false
y el campo Value
se le asignará por default(T)
en caso de int?
sería 0
.
Ahora cuando llamamos a ToString
en _cost
, Nullable<T>
tiene una definición de reemplazo de ToString
, que si miramos la referencia de origen proporcionada por Microsoft se implementa como:
public override string ToString() {
return HasValue ? value.ToString() : "";
}
Por lo tanto, devuelve una cadena vacía, ya que _cost
se asigna null
.
Ahora viene el caso de string _serialNumber
. Al ser una string
, es un tipo de referencia y puede contener puramente null
. Si mantiene null
, llamar a ToString
generaría la excepción de referencia nula como se esperaba.
Puede ver: Tipos de valores y tipos de referencia: MSDN
Un Nullable<int>
es una struct
y realmente no puede ser nulo. Por lo tanto, una llamada a un método en una estructura "nula" todavía funciona.
Hay algo de "magia del compilador" que hace que _cost == null
una expresión válida.
Una cadena es un tipo de referencia, pero una int nullable es un tipo de valor. Aquí hay una buena discusión de las diferencias http://www.albahari.com/valuevsreftypes.aspx .
lo que creo que es el motivo, cuando el compilador encuentra un tipo de datos primitivos que lo envuelve, a su objeto correspondiente. La llamada al método toString () es simplemente una llamada indirecta (envolviendo y luego llamando al método) aquí y la excepción se maneja allí. Mientras que en el caso de String, estamos llamando directamente al método. Cuando apunta a un valor nulo, el método arroja la excepción.
int?
no es realmente un objeto en sí mismo, pero es un objeto Nullable<int>
.
Entonces cuando declaras int? _Cost
int? _Cost
, en realidad estás declarando Nullable<int> _Cost
y la propiedad de _Cost.Value
undefined
está undefined
no es el _Cost
objeto en sí.
En realidad, es un azúcar sintáctico para usar fácilmente tipos que
non nullable
comoint
,bool
odecimal
.
De acuerdo con MSDN :
La sintaxis
T?
es una abreviatura deSystem.Nullable<T>
, dondeT
es un tipo de valor. Las dos formas son intercambiables.
TextBox2.Text = selectedItem.SerialNumber.ToString(); //error
error de yiels porque está llamando a la función ToString() que es miembro de System.String . Esta función devuelve esta instancia de System.String; no se realiza una conversión real. Además, String es un tipo de referencia. Un tipo de referencia contiene un puntero a otra ubicación de memoria que contiene los datos.
TextBox1.Text = selectedItem.Cost.ToString(); //no error
no produce ningún error porque llama a la función ToString() que es miembro de System.Integer . Esta función convierte el valor numérico de esta instancia a su representación de cadena equivalente. Además, Integer es un tipo de valor. Un tipo de datos es un tipo de valor si contiene los datos dentro de su propia asignación de memoria.
El mismo nombre de función ToString () pero realiza una tarea diferente.