Pregunta

He estado buscando una buena guía sobre esto desde que el concepto se introdujo en .net 2.0.

¿Por qué querría usar tipos de datos no anulables en C #? (Una mejor pregunta es por qué no elegiría tipos anulables por defecto, y solo usaría tipos no anulables cuando eso tiene sentido explícitamente).

¿Existe un impacto 'significativo' en el rendimiento para elegir un tipo de datos anulable en lugar de su par no anulable?

Prefiero comparar mis valores con nulos en lugar de Guid.empty, string.empty, DateTime.MinValue, < = 0, etc., y trabajar con tipos que aceptan valores NULL en general. Y la única razón por la que no elijo tipos anulables con más frecuencia es la sensación de picazón en la parte posterior de mi cabeza que me hace sentir que es más que la compatibilidad con versiones anteriores lo que obliga a ese '?' Adicional carácter para permitir explícitamente un valor nulo.

¿Hay alguien por ahí que siempre (casi siempre) elige tipos anulables en lugar de tipos no anulables?

Gracias por su tiempo,

¿Fue útil?

Solución

La razón por la que no siempre debe usar tipos anulables es que a veces puede garantizar que se inicializará un valor . Y debe intentar diseñar su código para que este sea el caso con la mayor frecuencia posible. Si no hay forma de que un valor no pueda ser inicializado, entonces no hay razón para que nulo sea un valor legal para él. Como un ejemplo muy simple, considere esto:

List<int> list = new List<int>()
int c = list.Count;

Esto es siempre válido. No hay forma posible de que c no se pueda inicializar. Si se convirtió en un int?, efectivamente le estaría diciendo a los lectores el código & Quot; este valor podría ser nulo. Asegúrese de verificar antes de usarlo & Quot ;. Pero sabemos que esto nunca puede suceder, entonces, ¿por qué no exponer esta garantía en el código?

Tiene toda la razón en los casos en que un valor es opcional. Si tenemos una función que puede o no devolver una cadena, entonces devuelve nulo. No devuelva string.Empty (). No devuelva & Quot; valores mágicos & Quot ;.

Pero no todos los valores son opcionales. Y hacer que todo sea opcional hace que el resto de su código sea mucho más complicado (agrega otra ruta de código que debe manejarse).

Si puede garantizar específicamente que este valor siempre será válido, ¿por qué descartar esta información? Eso es lo que haces al convertirlo en un tipo anulable. Ahora el valor puede o no existir, y cualquiera que lo use tendrá que manejar ambos casos. Pero usted sabe que solo uno de estos casos es posible en primer lugar. Entonces, haga un favor a los usuarios de su código y refleje este hecho en su código. Cualquier usuario de su código puede confiar en que el valor sea válido, y solo tienen que manejar un solo caso en lugar de dos.

Otros consejos

Porque es inconveniente tener que verificar siempre si el tipo anulable es null.

Obviamente, hay situaciones en las que un valor es realmente opcional, y en esos casos tiene sentido usar un tipo anulable en lugar de números mágicos, etc., pero siempre que sea posible, trataría de evitarlos.

// nice and simple, this will always work
int a = myInt;

// compiler won't let you do this
int b = myNullableInt;

// compiler allows these, but causes runtime error if myNullableInt is null
int c = (int)myNullableInt;
int d = myNullableInt.Value;    

// instead you need to do something like these, cumbersome and less readable
int e = myNullableInt ?? defaultValue;
int f = myNullableInt.HasValue ? myNullableInt : GetValueFromSomewhere();

Creo que los diseñadores de lenguaje sienten que 'los tipos de referencia que se pueden anular por defecto' fue un error, y que no anulables es el único valor predeterminado razonable, y que debería optar por la nulidad. (Así es en muchos lenguajes funcionales modernos.) & Quot; null & Quot; suele ser un montón de problemas.

Parece que tienes 2 preguntas diferentes ...

  

¿Por qué querría usar tipos de datos no anulables en C #?

¡Simple, porque el compilador garantiza que los datos de tipo de valor en los que confía tienen realmente un valor!

  

¿Por qué no elegiría tipos anulables por defecto, y solo usaría tipos anulables cuando eso tiene sentido explícitamente?

Como ya ha mencionado Joel, un tipo solo puede ser nulo si es un tipo de referencia. El compilador garantiza que los tipos de valor tienen un valor. Si su programa depende de una variable para tener un valor, entonces este es el comportamiento que querrá al no elegir un tipo anulable.

Por supuesto, cuando sus datos provienen de cualquier lugar que no sea su programa, entonces todas las apuestas están canceladas. El mejor ejemplo es de una base de datos. Los campos de la base de datos pueden ser null, por lo que querrá que la variable de su programa imite este valor, no solo crear un & Quot; magic & Quot; valor (es decir, -1, 0 o lo que sea) que " representa " <=>. Lo haces con tipos anulables.

Aunque los valores nulos pueden ser convenientes para usar como " not-initialized-yet " o " no especificado " valores, hacen que el código sea más complejo, principalmente porque está sobrecargando el significado de null , así como la variable (número-o-nulo frente a solo-un-número).

Los valores NULL son favorecidos por muchos diseñadores de bases de datos y programadores de bases de datos SQL, pero con un pequeño cambio en el pensamiento sobre el problema, puede eliminar los valores nulos y tener un código más simple y confiable (por ejemplo, no se preocupe por NullReferenceException s )

En realidad, hay una gran demanda de " T! " operador que hace que cualquier tipo de referencia no sea anulable, similar a cómo " T? " hace que los tipos de valor sean anulables, y Anders Hejlsberg, el inventor de C #, deseó haber incluido la habilidad.

Vea también la pregunta, ¿Por qué es & # 8220; nulo & # 8221; presente en C # y Java?

Tiendo a usar tipos anulables donde sea que tengan sentido: no me preocupará el rendimiento hasta que sea un problema, luego arreglaré las pocas áreas donde está y terminaré con él.

Sin embargo, también encuentro que, en general, la mayoría de mis valores terminan siendo no anulables. De hecho, hay muchas veces que me gustaría un NotNullable que pueda usar con tipos de referencia para descubrir un problema nulo cuando obtengo el nulo, y no más tarde cuando trato de usarlo.

La única vez que se debe usar un tipo anulable es en el caso de que un determinado campo en una tabla de la base de datos requiera absolutamente que la aplicación envíe o reciba un valor nulo en algún momento. Incluso en tal caso, uno siempre debe tratar de encontrar una manera de usar el Tipo Nullable. Bool no siempre es tu mejor amigo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top