Nullable Types (bueno tampoco existe en Java)
Un tipo Nullable puede representar el rango normal de valores del tipo de dato al que hace referencia en su parámetro, pero además permite un valor null en la variable que se este utilizando. Por ejemplo si queremos utilizar un entero tendriamos algo como esto: Int32 x;, lo cual almacena valores entre [-2147483648 a 2147483647], pero si hacemos lo siguiente: Nullable x; se podrá almacenar el mismo rango de valores pero además un valor de null, lo mismo pasa con los otros tipos de dato (por ej: bool [true, false, null], tres valores)
Bueno alguien puede preguntar y esto para que sirve, bueno en realidad su aplicación se ve cuando se está trabajando con BD, cuando utilizamos un framework por ejemplo, podremos decir "que campos son obligatorios, cuales no" :). Ya habiamos hablado antes de esto con un docente, mencionando que en los lenguajes hasta entonces (por lo general) no tenían una forma de especificar en una clase, con relación a la BD, podrian ser obligatorios, cuales llaves foráreas, cuales llaves, etc. Es cierto que esto se define en los mapeos a la BD, sin embargo cuando se trabaja con varias personas (lo que es casi obligatorio hoy en día), muchas veces los desarrolladores se encargan de una parte del desarrollo en la que no tiene porque ver más alla de donde trabaja, es decir solo conocer los servicios de otros componentes, módulos y subsistemas. Entonces para conocer que campos se deben registrar, cuales son obligatorios para el control, etc. uno debe bajar a ver el diseño de la BD :).
Bueno creo la cosa va por ese camino, desde mi punto de vista me parece excelente cuando se hace un mapeo a la BD desde clases y este mapeo ya genera los campos no null o los que si pueden ser :).
Palabras clave: C#, Tipos Nullable
Comentarios
No le veo mucha diferencia a usar
Integer valor=null;
o en general
Object valor =null;
Apoyo tu idea Wilfredo, sería interesante ver un uso práctico
Si, queremos entender más sobre lo interesante que pueden ser estos tipos Nullable. Al parecer por lo que vi:
Primera línea: tipo Nullable Int para la variable unknown1, valor es null.
Segunda línea: tipo normal.
Tercera línea: operación de un tipo Nullable con un tipo normal. Supuestamente la operación no debiera realizarse, y dar una excepción. ¿Correcto? Caso contrario, ¿cuál es el valor de result1? Segunda observación ... los tipos son realmente distintos, en caso contrario la operación no requeriría el uso de una coerción (denominada cast).
Si son tipos distintos, ¿cuál es la lógica del cálculo de valores para estos tipos distintos? (una lógica polivalente sin duda ...)
En Haskell se puede usar el tipo Maybe para crear un tipo de datos que pueda resultar en una lógica polivalente. El tipo Maybe usa dos constructores: Just para el caso de que haya un resultado y Nothing para el caso que no tenga. Podemos definir un nuevo tipo de datos:
Y para sobrecargar los operadores hay que instanciar las clases que correspondan (Numeric, etc). La lógica polivalente se hace explícita, y se debe pensar para proveer los operadores con los cuales se van a manipular los tipos.
Por lo que también pude investigar, la forma de implementar el Nullable type es usando genéricas. Entonces tengo la intuición de que es algo así como el Maybe solo que un poco más adecuado al paradigma.
Para el mapeo en BD de datos es automático??? y que tipo de dato genera en BD si al parecer no tiene un tipo claramente definido (varchar, int, double, etc)
Ahora con lo referente a Java, existe el JPA que el mapeo lo hace automatico y puede especificar @Notnull con lo que logras el mismo efecto
Analizando el mapeo objeto-relacional en aspectos de obligatoriedad-opcionalidad de la presencia de valores de un atributo:
Si los tipos de datos que se estan analizando son: String, VarChar, Date, Blob, RAW....o tipos similares, Es posible que en la vida real exista una gran probabilidad de que puedan adquirir valores nulos (o ausencia de valores), tal el caso de un atributo FECHA_FIN-->DATE que pueda contener un valor nulo, representando la inexistencia de ese valor en la vida real.
Seguimos analizando: Si los tipos de datos que se estan analizando son: int, float,real..u otros similares (enum) entonces en el mundo real representan aspectos que pueden tomar solamente esos valores....y definen en el mismo conjunto su propio default value o su propio nulo, asi conceptualmente, el valor nulo en los números es por lo general el 0 (cero), pues siguen la lógica del conteo...de la sucesión...etc, Entonces No es buena practica permitir valores nulos en la BD, por tanto no hay que preocuparnos mucho de reproducir esas posibles chacreadas en el lado objeto.
seguimos analizando: el problema se pone feo con otros tipos de datos, como Boolean o similares que NO definen un defalut value o nulo....pues No hay nulo para una disyuntiva booleana. Nuevamente nos enfrentamos a la coherencia de modelarlo correctamente en relacional. Tomando en cuenta que en la vida real no es coherente dar otra salida (null) a disyuntivas booleanas, entonces no deberia ser coherente modelaras.
C# = C++/C + Java + Otras Caracterisiticas
Pablo en su respuesta respuesta de Pablo entrega una explicación del uso de nullable types y las compara con MayBe de Haskell. Estoy de acuerdo en su percepción de la implementación de estos tipos.
Marcelo en su respuesta respuesta de Marcelo a esta entrada nos pone a pensar en lo que significan los null en la base de datos y las consecuencias de su práctica que se ve reflejada en el código de un programa en C# que debe controlar la ausencia de valores en algunos atributos (campos obtenidos de una BD). Creo también que es correcta su percepción; sin embargo vale la pena, como programadores, tener alternativas para el manejo de situaciones inesperadas en nuestras aplicaciones. La tecnología de BD admite la existencia de los null y deben ser tratados!. Estamos frente al manejo de excepciones y efectos colaterales que suceden de las mismas (Java maneja excepciones ;)), aqui entra la ventaja del uso tipos con lógica polivalente y es una de las aplicaciones del tipo MayBe en Haskell. Supongo al igual que Pablo que nullable types es la impementación de la idea MayBe de Haskel en C#, lo que sería positivo; por el momento es una intuición saludable.
Por otro lado el siguiente comentario: Null pointers vs None vs Maybe habla de las bondades de MayBe, entre ellas la posibilidad de tipo recursivo que aparentemente C# con nullable types carece.
Sin duda los nullable types son útiles y una idea inetersante, lo malo es la cohersión de tipos que implica int es distinto de int?. Algo no muy bueno a mi parecer.
Creo que Marcelo está haciendo unas generalizaciones un poco peligrosas. En los tipos de datos que menciona propensos a ser nulos, son solo eso. No entiendo por qué decir que pueden serlo con alta probabilidad en algún momento de su vida. Si razonamos de la forma más conservadora posible, por supuesto TODO campo de la base de datos puede ser nulo (y por tanto su tipo ser Nullable), pues se puede dar la posiblidad de que ese valor se desconozca temporalmente. ¿Es esta una situación razonable? Creo que estas posibilidades intentamos reducirlas al mínimo pues nos interesa tener bases de datos con información útil. Seguramente en algunos casos es interesante la posiblidad de que todos los campos no estén llenos. Eso dependerá de la calidad de la información que nos importa tener en un campo y no tanto del tipo de dato. Cosa análoga con los tipos numéricos.
En base de datos la situación no es demasiado crítica excepto para campos llave. ¿Permitiríamos llaves artificiales nulas? Jamás. ¿Permitiríamos llaves naturales con valores nulos? En teoría jamás. En la práctica pienso que muchos ni siquiera saben cuales son las llaves naturales de sus tablas (teoría de bases de datos relacionales, dependencias funcionales, etc, ¿les suena conocido?). Pienso que el razonamiento va por ahí.
En el paradigma OO el valor nulo tiene más impacto. Nada tiene que ver el estado en ello, pues también la lógica de su tratamiento se encuentra en lenguajes funcionales. El punto es que en OO te importan las operaciones. Las mismas reflejan la lógica de operación con los valores. Esta lógica ya no solamente debe operar con valores posibles de ser calculados, sino con valores inexistentes, y con tipos de valores inexistentes. A veces quieres distinguir entre los tipos de inexistencias, como se menciona en el artículo que Vladimir ha tenido la gentileza de referir en su respuesta.
Vladimir: ¿ int es distinto de int? ? ¡Por supuesto! No es lo mismo un valor VERDADERO cuando no existe la posibilidad de decir NO SE, que cuando la existe. Son dos lógicas distintas. Hay que extender la lógica bivalorada a una lógica trivalorada. En el mejor de los casos, la lógica trivalorada extenderá naturalmente la lógica bivalente clásica, pero no tiene que ser así necesariamente.
Para terminar me gustaría resaltar lo que se menciona en el post que Vladimir nos apuntó: lo interesante de Haskell es que se explicita la situación del manejo de los valores, y no se toma por defecto una forma lógica establecida (como en otros lenguajes). No es necesario tomar exactamente el tipo Maybe, uno puede inventar su propio tipo que tenga la lógica del Maybe y definir las operaciones que sean necesarias para manejar los valores establecidos.
from de craddle:
Las llaves primarias y atributos con caracteristica NOT NULL en bases de datos NO son problema en el mundo Objeto (ya sea con C#, Java o cualquier lenguaje), pues es posible controlar la obligatoriedad de sus valores explicitamente en las operaciones de creación de esos objetos (constructores, sets()) El problema surge cuando a pesar de tener una obligatoriedad en el mundo real, el diseñador de BD permite que adquiera valores nulos (no los diseña con la restricción NOT NULL), asi la gran pregunta del diseñador de los programas en el lado objeto debe ser: ¿debo tambien permitir que adquieran valores nulos?
Si la respuesta es SI: gran chacreada, es una decisión que propaga el mal diseño de la BD hacia los programas, con el consiguiente riesgo/ inestabilidad de los programas, además que el programador empezará a buscar elementos que le permitan manejar las situaciones complejas de manejar basura.
Si la respuesta es NO: sabia decisión, aunque hay mas trabajo, habrá que hacer una refactorización al diseño de la BD..y tal vez también una depuración de los datos que contiene, pero la ventaja será que los programas no tendrán que manejar situaciones extrañas (menos complejo) y ya no se tratará de reciclar basura, no se intentará programar cosas extrañas que pueden tener side effects y otros peligros.
Ahora...¿por que aceptar valores nulos en atributos definidos con un tipo?..no es acaso una contradicción?
En BD, es una costumbre..asi por la explicación de Pablo, es posible que aun no se tenga la información para algunos de ellos y no sea aplicable darle un valor de su tipo definido, sin embargo ¿No es acaso este hecho tambien una situación prevista ?¿por que no preveer entonces que el tipo de dato con el que se modela provea esos valores nulos?, la respuesta para el diseñador de Bases de Datos está en definir dominios y clasificadores(del lenguaje de idioms) para preveer estas situaciones.....en contrapartida a la acostumbrada forma de permitir nulos que no estan definidos en el tipo.
#17. De acuerdo con algunas cosas, NULL indica lo que dices, por supuesto es muy diferente a un estado X, muchos confunden este detalle cuando tienen estructuras dinamicas vacias o nulas :)
Bueno el hecho de que Java tenga las clases que mencionas (algunas de ellas las Wrapper), no significa que se parezcan a los nullables, de hecho en C# cuando pones algo como:
Nullable<short> edad;
La variable edad ahora tiene algunas propiedades interesantes, por ejemplo puedes hacer algo como:
if( edad.HasValue ) // Pensemos que edad es nulo, lanzara una excepcion de NullReferenceObject (o en Java NullPointerException)?
Bueno, en realidad los nullables en C# permiten manejar los objetos de manera bastante interesante, ademas con esto también puedes programar definiendo cuales de tus variables (objetos) pueden ser nulos y cuales no "deberian" serlo.