¿Hay alguna diferencia entre la variable de tipo de referencia no inicializada o que tiene un valor nulo? Leí en alguna parte que no-init significa nulo pero en otro lugar leo algo más. ¡Gracias!Valores no inicializados frente a valores nulos de los tipos de referencia
Respuesta
Tenga en cuenta que los campos se inicializan de manera implícita a null
, así que esto sólo afecta a las variables. En pure C# usted no puede consultar el valor de un campo no inicializado (necesita "asignación definitiva"), por lo que no es cuestión.
Usted puede hacer esto mediante el abuso de IL aunque - al declarar un parámetro out
, y el uso de DynamicMethod
escribir un método que no asignarla (válido en IL, pero no en C#). Y luego verá que verá null
s.
Esto a su vez se debe a una bandera IL (.locals init
) que dice "borrar la pila para mí antes de entrar en este método" en la llamando código (C#). El compilador de C# siempre establece este indicador. Si vuelve a abusar de IL para escribir un método que no establece este indicador, probablemente pueda ver basura. Podría ser cualquier cosa. Pero en este punto, que se merece las excepciones se obtiene :)
He aquí un ejemplo de la primera (no el segundo, que es más complejo):
delegate void AbuseMe(out object foo);
static void Main() {
DynamicMethod dyn = new DynamicMethod("Foo",
typeof(void), new[] { typeof(object).MakeByRefType() });
dyn.GetILGenerator().Emit(OpCodes.Ret);
AbuseMe method = (AbuseMe) dyn.CreateDelegate(typeof(AbuseMe));
object obj; // this **never** gets assigned, by **any** code
method(out obj);
Console.WriteLine(obj == null);
}
Para mayor claridad, el código DynamicMethod
es simplemente escribiendo el equivalente a este código, no es legal en C#:
static void Foo(out object whatever) { } // note, whatever is not assigned
esto funciona porque por lo que el CLR se refiereout
no existe - sólo hay ref
. Entonces, esto no es inválido. IL: solo el lenguaje (C#) le da significado al out
y exige que se le asigne un valor.
El problema es que Main()
todavía tiene la bandera .locals init
; así que detrás de las escenas obj
está borrado a null
(bueno, todo el espacio de la pila simplemente se borra). Si compilé desde IL sin esa bandera (y tenía algún otro código en su lugar para ensuciar el espacio de la pila) pude ver basura. Puede ver más sobre .locals init
en el blog Liran Chen's.
Pero para responder a la pregunta: ¿
- de campos: campos de tipo de referencia sin inicializar son
null
- garantizado por la especificación - para las variables: no se puede pedir, pero como una implementación detalle (que no hay que dependía): sí, será
null
a pesar de que no se puede pedir; p
"depende"
Para variables normales miembro cuando un valor no está especificado en la declaración entonces la variable asume el valor predeterminado adecuado (null
para los tipos de referencia). Es decir, class A { string X; }
es lo mismo que class A { string X = null; }
.
Para variables locales es un error acceder a ellas antes de que se pueda demostrar que se ha asignado un valor. A pesar de que su tipo "predeterminado" es nulo (para tipos de referencia), ¡no están predeterminados por defecto! Es decir, string F() { string x; return x; }
es un error en tiempo de compilación.
Recuerde: null
es null
:-)
- 1. Deberían los enums tener valores no inicializados.
- 2. ¿Los valores nulos ahorran espacio de almacenamiento?
- 3. SQL: Usando los valores NULL frente a los valores por defecto
- 4. ¿Puede un método genérico manejar los tipos de valores de referencia y valores anulables?
- 5. tipos de valores inmutables
- 6. Predeterminado para valores nulos
- 7. C# - LINQToExcel - Valores Nulos
- 8. Tipos de referencia no anulables
- 9. ¿Cuáles son las diferencias entre los tipos de valores y los tipos de referencia en C#?
- 10. ¿Cómo manejan los tipos anulables los valores nulos con los operadores de comparación?
- 11. reemplazar los valores nulos en pivote sql
- 12. NSSortDescriptor y valores nulos
- 13. Los datos son nulos. No se puede llamar a este método o propiedad en Valores nulos
- 14. MySQL GROUP_CONCAT con valores nulos
- 15. Pasar tipos de valores inmutables por referencia de forma predeterminada
- 16. En C#, el uso de los tipos de valor frente a los tipos de referencia
- 17. Tipos de referencia que no admiten nulos (una vez más)
- 18. Cómo pedirle a BeanUtils que ignore los valores nulos
- 19. Seleccionar valores nulos en SQLAlchemy
- 20. PHP/MySQL Insertar valores nulos
- 21. Valores de Concat en MySQL Query (para manejar valores nulos)
- 22. indexación valores nulos en PostgreSQL
- 23. Leer valores nulos del archivo
- 24. ¿Cómo puedo acercarme a los tipos de referencia que no admiten nulos en C# hoy?
- 25. columnas con valores nulos Actualizar
- 26. ¿MySQL 5.0 indexa valores nulos?
- 27. ¿Cuándo Oracle indexa valores nulos de columna?
- 28. Hibernate Valores nulos para @CollectionOfElements
- 29. ¿Insertar valores nulos en campos de fecha?
- 30. Cómo .NET diferencia los tipos de referencia frente a primitivo y de valor
Ok, eso es bastante extraño sh! T! :) – leppie
@leppie Quiero agradar; p –
Jeffrey Richter en su libro "CLR Via C#, 3rd edition" menciona que las variables siempre se inicializan por CLR a 'null'. También dice que en realidad no es necesario que el compilador de C# prohíba el uso de variables no inicializadas, pero el compilador todavía tiene esta restricción. –