Olá! Thursday, 18 de April de 2024.



Dicas CódigoFonte.net
Thursday, 17 de May de 2007

Nullable Types

Olá a todos.

O .Net 2.0 traz um recurso deveras interessante, embora, à primeira vista, não o pareça.

Primeiro: Revendo Value-Types e Reference-Types
Antes de falar de Nullable types, é necessário relembrar a diferença entre value-types e reference-types. Se você já conhece bem esta diferença, você vai achar mais interessante ir para o próximo tópico.

Value-types e Reference-Types são os primeiros grandes grupos de tipos do .Net, dos quais todos os outros tipos derivam. O primeiro grupo (value-types), compreende todos os tipos de dados numéricos (byte, sbyte, int, uint, long, ulong, char, bool, float, double e decimal) bem como Enumeradores (enum) e Structures (struct).

Value-types são alocados no Stack. Isto faz com que eles sejam facilmente removidos da memória uma vez que eles ficam fora de escopo. Quando você atribui o valor de uma variável de um tipo value-type para outra, uma cópia do seu valor é atribuído para a outra. No caso de duas variáveis do tipo int, seu valor é simplesmente copiado (chega a ser redundante repetir isto). Mas no caso de uma struct, a cópia realizada é uma cópia de membro por membro.

Começamos o primeiro exemplo, definindo um struct. O struct NomeCompleto guarda Nome e Sobrenome:

Clique para ver a imagem em seu tamanho real

Este pequeno programa, irá copiar um NomeCompleto para outro e logo após fará alteração em um dos membros.

Clique para ver a imagem em seu tamanho real

Ao fazer a cópia, observe que nomeCompleto2 possui o mesmo conteúdo de nomeCompleto1. Mas ao fazer a alteração no sobrenome de nomeCompleto2, você nota que nomeCompleto1 permanece com o estado original. Isto se dá por que, diferente das classes, que são reference types, as structs são value-types, e passam todos os seus valores quando são atribuídas a alguém.

Clique para ver a imagem em seu tamanho real

Se eu simplesmente redeclarar a struct como class, o resultado altera de forma considerável. Isto por que class é um reference type, o que significa que, na atribuição, ele não recebe os valores contidos no objeto, mas sim uma referência ao endereço que o mesmo ocupa na memória. Sendo assim, tudo o que for aplicado a um, reflete no outro. (Na verdade, o que se aplica em um reflete somente nele mesmo, e isto faz com que as alterações sejam visíveis nas outras referências.) Observe o resultado do mesmo programa, apenas alterando a declaração do struct NomeCompleto para class:

Clique para ver a imagem em seu tamanho real

Note que quando mudamos o sobrenome de nomeCompleto2, a alteração também se torna visível no nomeCompleto1.

Clique para ver a imagem em seu tamanho real

No fim das contas, Value-Types são tipos que administram os próprios valores. Sempre se copiando ao serem manipulados. Reference-Types são tipos que administram referências a objetos alocados na memória. Agora que você entende esse tópico básico, você está pronto para conhecer o recurso tema deste artigo: Nullable Types.

Nullable Type Itself

Existe uma limitação que nunca foi realmente um problema (mas vale a pena conhecer sua solução). Variáveis de um tipo value type não aceitam valores nulos. Sendo assim, atribuir um valor null a uma variável do tipo int provocava um erro de compilação.

Nós aprendemos a lidar com esta limitação do framework, usando flags como int.MinValue para indicar valores inválidos ou algum outro tipo de tolerância.

Com o recurso de Nullable types disponível (sinceramente eu não consigo encontrar uma tradução saudável para o termo Nullable em português) conseguimos alguma trégua para lidar com isto de uma forma mais polida.

Suponhamos a situação da seguinte (e muito simples) tabela:

Clique para ver a imagem em seu tamanho real

O primeiro registro possui um valor no campo Idade, mas o segundo, por alguma razão, foi deixado como Null.

Clique para ver a imagem em seu tamanho real

O seguinte código vai provocar um erro quando o registro lido for o de Burns.

Clique para ver a imagem em seu tamanho real

Isso por que o campo Idade possui um valor Null, que é inaceitável para uma variável do tipo byte, e isso provoca uma SqlNullValueException. A manobra que se fazia era setar a variável com o minValue específico do seu tipo e verificar se o campo é nulo antes de fazer a atribuição.

Nullable types são tipos criados especificamente para este tipo de situação: Atribuir valor Null a variáveis de algum tipo Value Type.

Somente value types podem se tornar nullable types e a forma de fazer isto é muito simples. Usando o operador "?" ao lado da indicação de tipo. Exemplo:

Clique para ver a imagem em seu tamanho real

Desta forma, valores nulos poderão ser associados à estas variáveis.

Outras Utilidades

Como desenvolvedor, você precisa ter em mente de que as situações onde se aplicam recursos como Nullable Types são inesperadas. À primeira vista pode parecer um recurso inútil, mas no seu dia-a-dia vai compensar ter conhecimento deste recurso por ser aplicável a uma circunstância inesperada.

No meu caso, enums e structs.

Quase todos os enums de um determinado projeto do qual eu fazia parte, precisavam contemplar um elemento None pelo simples fato de não ser possível atribuir null à ele. O mesmo para structs que deveriam ser usados em determinados pontos.

Acreditem quando eu digo, mais vale a pena ter conhecimento de um recurso e nunca precisar usá-lo do que precisar sem nunca saber de sua existência.

O Operador "??"

Uma mão na roda para auxiliar ainda mais no uso de Nullable types, é o operador "??". Ele dá uma alternativa de valor para o caso do operando ser nulo. Por exemplo:

Clique para ver a imagem em seu tamanho real

O operador "??" verifica se o operando velMax possui valor Nulo e, no caso de ser verdade, como forçamos na linha anterior, dá um valor alternativo (80).

Clique para ver a imagem em seu tamanho real

A classe System.Nullable

O suporte a Nullable Types no .Net é permitido pela ocasião da Classe System.Nullable (Que também foi criada por ocasião do uso de Generics). Todos os NullableTypes na verdade são wrappers para instancias de Nullable. Ou seja, "int?" é um wrapper parar Nullable, "float?" é um wrapper para Nullable, e assim por diante.

É possível confirmar isso abrindo o código IL gerado pelo compilador. Ou, menos complicado para os que não conhecem IL, executando um código como este:

Clique para ver a imagem em seu tamanho real

E verificando o seguinte resultado:

Clique para ver a imagem em seu tamanho real

Ambos tipos, em design-time, são o mesmo tipo em run-time, ou seja, mapeiam um mesmo tipo durante a compilação.

Conclusões

Este pequeno artigo mostrou que, apesar disso nunca ter sido realmente um problema sério (talvez por que todos nós nos acostumamos com a limitação) os value types, que não suportavam valor nulo, receberam tipos equivalentes que o suportam: Nullable Types.

Com Nullable Types algumas limitações dos value-types podem ser superadas. Ainda que você não veja utilidade alguma nisto, e resolva nunca fazer uso deste recurso, tenha em mente que ainda assim pode ser útil conhecê-lo, pois ele cai no exame para a certificação.

Por Daniel Moreira Yokoyama

Daniel Moreira Yokoyama ([email protected]) atua na Envision Tecnologia, no desenvolvimento de um sistema web de pesquisa por disponibilidade e reserva de assentos em vôos para uma grande consolidadora de agentes de viagem. É formando em Ciência da Computação e trabalha com desenvolvimento há mais de 7 anos, tendo contato didático com .Net desde a aparição do primeiro beta do VisualStudio.Net e trabalhando com ele há quase 3 anos.

Conheça nosso parceiro:


Comentários do artigo [Novo comentário]

Nenhum comentário, seja o primeiro a comentar.
Para adicionar um comentário você deve efetuar o login


Gostou do CódigoFonte.net? Quer indicar a um amigo?
Preencha os campos a seguir.
Seu Nome:
Seu E-mail:
E-mail de seu Amigo:


CodigoFonte.net » Meu Mural » Competiva - Criação de Sites » Todos os Direitos Reservados © 2002/2010