Tipos amortables en C #, ou como vivir con nules

indiscelamente, os nulos son un dos peores pesadelos do desarrollador e causan unha gran cantidade de erros a tempo de aplicación. A falta de ferramentas para tratalos de forma adecuada fai a convivencia coas ovellas negras dos valores posibles que se aplicarán a unha variable. Neste artigo no Manual .NET imos tratar de lanzar un pouco de luz e dicirlle as solucións que a tecnoloxía nos ofrece a vivir cos valores nulos.

e é que con pouco que desenvolveu , seguro que xa atopou a difícil tarefa de asignar un valor nulo a unha variable de tipo de valor (int, flotante, char …) onde non encaixa máis que usar trucos difíciles de realizar, rastrexar e documentar. Por exemplo, dada unha clase de clase con unha propiedade de tipo enteiro chamada Idade, que pasa se tomamos un obxecto de devandita clase desde unha base de datos se o campo non era obrigatorio neste?

a priori, fácil: Ao ler a partir da base de datos comprobamos se é nulo e, nese caso, asignamos á propiedade do valor de clase -1. Bo parche, sen dúbida.

Con todo, optar en xeral por esta idea presenta varios inconvenientes. En primeiro lugar, para ser fiel á realidade, se nos gustaría almacenar de novo este obxecto na base de datos, debe realizarse o cambio inverso, é dicir, comprobar se a idade é -1 e nese caso garda no campo un nulo.

segundo, fixado que estamos levando aos artificios de clase que non teñen sentido no dominio do problema a resolver, na entidade á que representa. Mirándoo un pouco de lonxe, cal é o significado dunha idade negativa nunha entidade persoa? Ningún.

En terceiro lugar, hai un problema de consistencia nas consultas. Se teño unha colección de persoas en memoria (realizada, por exemplo, usando tipos xenéricos) e quero saber aqueles que están definidos por idade, debo comprobar se cada elemento se vale a súa idade de propiedade -1; Non obstante, ao realizar a mesma consulta na base de datos, debes solicitar o valor nulo no campo correspondente.

True é que tamén poderiamos traer o concepto á base de datos o concepto “-1 significa nulo” en O campo de idade, pero … non estariamos salpicando a estrutura de datos cunha particularidade (e limitación) da linguaxe de programación usada? Outra idea bizarra podería ser introducir a idade nunha cadea e un problema resolto: as cadeas, sendo un tipo de referencia pode conter nulos sen problemas, pero é necesario recoñecer que as ordes serían regulares; -)

por Último, e se no canto de idade, onde claramente non pode haber negativos, estabamos falando da clase de contos e a súa propiedade dartal? Aquí vese claramente que o uso de negativos non é un recurso válido.

Solutions, ademais dos comentarios, hai para todos os gustos. Podería, por exemplo, engadir unha propiedade booleana paralela que indicase se o campo de idade é nulo (un traballo extra, especialmente sen varias propiedades estes valores son), ou encapsulate a idade dentro dunha clase que incorpora o tratamento lóxico deste nulo.

En calquera caso, as posibles solucións son traballadores, ás veces complexos e, sobre todo, demasiado artificiais para ser algo tan diario xa que é un campo sinxelo.

consciente diso, c # Os deseñadores xa tiveron en conta na súa versión 2.0 unha característica interesante: tipos nulables ou tipos cancelables, un mecanismo que permite ao nulo nas nosas vidas de xeito non traumático.

A seguinte liña xerou un erro en Recopilación, que dixo, e non faltou razón, que “non se pode converter null en ‘int’ porque é un tipo de valor”:

int s = null;

A partir de C # 2.0, é posible facer o seguinte:

int? s;
s = null;
s = 1;

Observar o interrogatorio co tipo, que é a indicación de que a variable s é enteira, pero tamén admite un valor nulo.

Interior, isto funciona do seguinte xeito: int? É un alias do sistema de tipo xenérico. Nulado. De feito, poderiamos usar indistintamente calquera das dúas formas de expresalo. Internamente créase unha estrutura con dúas propiedades de só lectura: HASVALUE, que devolve se a variable en cuestión ten valor e valor, que contén o valor en si.

enténdese que unha variable con Hasvalue igual a Falso contén o valor nulo e, se intentamos acceder a ela a través do valor, será lanzado unha excepción.

Con todo, a principal vantaxe que teñen é que se usan coma se fose un tipo de valor tradicional. Os tipos cancelables compórtanse prácticamente coma eles e ofrecen os mesmos operadores, aínda que teñen que ter en conta as súas particularidades, como se pode ver no seguinte código:

int?A = 1;
int? b = 2;
int? INNULO = NULL;
bool? SI = TRUE;
bool? Non = falso;
bool? Nisinino = nulo;
consola.Writeline (A + B); // 3
Console.Writeline (A + INNULO); // nada, é nula
consola.Writeline (A * INNULO); // nada, é null
console.writeline (se & non); // false
consola.Writeline (se & non); // TRUE
consola.writeline (si & Nisinino); // nada, é null
console.writeline (non & nisinino); // false
consola.Writeline (SI | Nisinino); // TRUE
consola.Writeline (NON | NISININO); // nada, é nulo

Podemos crear tipos cancelables de calquera tipo de marco: int?, flotante?, dobre?, char?, etc.

e de feito, como tipos de valor que son, tamén podemos facelo con enumeracións. O seguinte exemplo sería incorrecto:

State State1 = status.Correct;
Estado do estado2 = null;

A segunda liña fai que o erro na compilación “null non se pode converter en ‘consolepplication1.program.state’ porque é un tipo de valor. ” Lóxico, é o mesmo que si intentamos asignar o valor maldito nulo a un enteiro.

Isto pode causar un pouco de incomodidade para a xestión de valores “indeterminados”, xa que sería necesario, por exemplo, a Use outro membro da enumeración para representar este valor, como no seguinte código en Visual Basic .NET:

Public Enum State a IndeTerminate = 0 CORICO = 1
incorrecto = 2
end enum

Con todo, hai momentos nos que é máis interesante poder ter un valor nulo como opción para as variables do tipo de enumeración. Para iso, podemos usar a mesma sintaxe que previamente vimos:

‘VB.NET
Dim status1 como nulable (de estado) = State.correct
State2 = Nada // C #
Estado? State1 = status.Correct;
Estado? State2 = NULL;

Nota: Este artigo está baseado en varias publicacións realizadas previamente no blog do autor, José María Aguilar, Variable non atopado

Deixa unha resposta

O teu enderezo electrónico non se publicará Os campos obrigatorios están marcados con *