O NeoMatrix Tech está de casa nova!

Você deverá ser redirecionado em 6 segundos. Se não, visite:
http://www.leonelfraga.com/neomatrixtech
e atualize seus favoritos.

Aviso IMPORTANTÍSSIMO!

Aviso aos navegantes:

O NeoMatrix Tech mudou de casa!!!

A partir de agora, acessem pelo novo endereço:

http://www.leonelfraga.com/neomatrixtech

Ué... mas é só o domínio mudou de lugar?

R: Na verdade, não é bem assim hehe. Este domínio que você acessa agora aponta para um blog hospedado no Blogger, enquanto no novo, aponta para um blog na plataforma Wordpress, hospedagem própria, muito mais rápida e com um layout mais agradável de ler ;)

Não vou fechar este domínio igual ao que eu fiz com o NM Light (que já está 100% na nova plataforma). Talvez beeeeeeem depois eu faça isso.

Todos os posts daqui se encontram lá, e novos posts serão colocados somente no novo endereço.
A única coisa que não consegui importar foram os comentários. Mas em breve vai ter um post contando sobre a epopéia que foi migrar o NeoMatrix Tech!

Somente vou fechar a área de comentários daqui. Caso queiram comentar, favor ver o post correspondente no "Novo NeoMatrix Tech" e comentem por lá. É bem melhor! (pena que os permalinks "amigáveis para SEO" não funcionam lá, dá erro 404 e não consigo fazer a configuração funcionar. E olha que eu já vi vários artigos falando desse assunto :( ).

Quem assina o feed, já está lendo o conteúdo do novo NeoMatrix Tech!

quarta-feira, 21 de janeiro de 2009

Tipos (Structs) "Nuláveis" em C# (exemplo: DateTime?) (Nullable Types)

Uma vez, quando fiquei alocado para arrumar um problema de desempenho em um programa em C# (um Windows Service que faz acesso a um banco Oracle e a um webservice) encontrei algo que me deixou curioso, uma declaração da seguinte forma:

   1: public DateTime? MinhaData;


Fiquei curioso pelo fato do ponto de interrogação que sucede o tipo DateTime (DateTime?). Nunca tinha visto este tipo de declaração.

Pesquisando o que significava, pensando que é algum tipo de modificador, descobri que se sucedermos um tipo de dados pelo ponto de interrogação, significa que poderemos atribuir o estado null para ele.

Como assim?

Se, por exemplo, atribuirmos null para uma variável do tipo DateTime ou int (só para citar mais de um), ocorrerá um erro de compilação (ou execução...) com a seguinte mensagem:

Cannot convert null to 'System.DateTime' because it is a value type

Os tipos DateTime e int dos nossos exemplos são implementados com struct, e de acordo com a mensagem acima, ele é um tipo por valor, ou seja, um tipo primitivo (armazena somente valores, como datas e números).

Tipos primitivos, embora tenhamos métodos sobre eles, não são objetos, que são tipos por referência (se você atribui um objeto A para o B, qualquer modificação no B refletirá em A, pois B faz uma referência a A - apontam para o mesmo endereço de memória -, e não é uma cópia de A - em outro ponto da memória.). Por causa dos métodos que temos é que eles são implementados sendo struct (que pode ter métodos, como uma classe). Só para ter uma noção da coisa, o tipo string do .NET é implementado como uma classe, ou seja, é um objeto, e portanto, é um tipo por referência e o estado nulo pode ser atribuído.

O ponto de interrogação "transforma" este tipo por valor em um tipo por referência, ou seja, significa que poderemos atribuir o estado null para variáveis dele.

Uma declaração do tipo abaixo não irá gerar erros de compilação ou execução:

   1: public DateTime? MinhaData = null;

Isto é útil principalmente quando atribuimos nestas variáveis valores oriundos de um banco de dados, que podem estar nulos ou não, e não queremos trabalhar a toda hora com variáveis string, como comumente é feito.

Como nem tudo na vida são flores, isso tem algumas desvantagens. Uma delas é que não temos mais as propriedades e métodos do struct DateTime (como AddDays, Month, Year, entre outros) diretamente. Veja a imagem abaixo, demonstrando o code-insight em uma variável DateTime? :

insight-1

Duas propriedades importantes deste novo tipo, como em qualquer outro tipo "nulável", são as propriedades Value e a HasValue. A primeira é a que conterá o tipo original em questão: Se for DateTime, ela será do tipo DateTime, se for int, será int.

Dentro da propriedade Value é que estarão todos os métodos do tipo original:

insight-2

A propriedade HasValue, do tipo bool, indica se a variável não é nula. Isto é importantíssimo no momento de fazermos ou uma atribuição para um tipo original, quanto para fazer comparações, no nosso caso, demonstrarei como um if a mais no código exemplo abaixo:

   1: DateTime x = DateTime.MinValue;
   2: DateTime? y = null;
   3:  
   4: if (x.Equals(y))
   5: {
   6:     MessageBox.Show("alguma coisa");
   7: }
   8:  
   9: if (x < y)
  10: {
  11:     MessageBox.Show("outra coisa");
  12: }

No código acima, devemos tomar alguns cuidados: Null é um ESTADO, e não um VALOR. Portanto, comparar as duas variáveis é um tiro no pé. No segundo if, quem é menor e quem é maior?

Esta pergunta não tem resposta! Null não é nem menor, nem igual, nem maior a um valor. A única comparação que será verdadeira será a da diferença. Não vai gerar exception no código acima, mas ele está ilógico. Já o exemplo abaixo vai dar um erro de execução, mas vai ser compilado:

   1: DateTime x = DateTime.MinValue;
   2: DateTime? y = null;
   3:  
   4: if (x.Equals(y))
   5: {
   6:     MessageBox.Show("alguma coisa");
   7: }
   8:  
   9: if (x > y.Value)
  10: {
  11:     MessageBox.Show("outra coisa");
  12: }

O erro será a seguinte mensagem:

Nullable object must have a value.

Isso significa, que antes de fazer o If, temos que verificar se existe algum valor na variável y. O correto a fazer é:

   1: if (y.HasValue)
   2: {
   3:     if (x > y.Value)
   4:     {
   5:         MessageBox.Show("outra coisa");
   6:     }
   7: }

Tivemos um trabalho a mais neste código.

Como vimos, este é um recurso que embora muito útil, devemos utilizá-lo com bastante cuidado para não termos surpresas lá na frente ;-)

Para saber mais: http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspx

Um abraço!

2 comentários:

Hugo,  5 de jun de 2009 07:32:00  

Obrigado!! Foi muito útil! :)

felipe,  19 de ago de 2009 17:57:00  

bom, bem explicado


Postar um comentário

Para tornar este artigo ainda mais interessante, escreva suas críticas (desde que construtivas e sem ofenças), elogios, sugestões, complementos, dúvidas, etc, etc, etc!!!

  © Blogger templates ProBlogger Template by Ourblogtemplates.com 2008 - Editado e configurado por Leonel F.

Voltar ao TOPO