Boa tarde amigos, eu precisei dar permissão para um atributo em meu objeto ser nulo, até ai tudo ok. O problema é a que quando eu preciso atribuir este valor a outra variável com o tipo igual ou até retornar em um método com o mesmo tipo este erro é exibido.
Bom eu tenho solucionado desta forma.: long.Parse(obj.Registro.ToString())
E o meu problema é… deve existir algo mais elegante para resolver este problema… ou é assim que devo proceder… pensei também em colocar o ponto de exclamação no método, mas mesmo assim exibe outro erro, algo que me força a retornar o valor válido.
o long? é tipo “pode ser nulo ou pode ser um long”, certo?
vc quer algo mais elegante que isso?
vamos la, se um atributo pode nulo e ai vc precisa controlar isso. se em algum momento vc quer um long, vc ignora que ele pode ser nulo.
o problema todo é a sua modelagem. vc considera uma parte dos casos. e só vc que pode resolver pq vc não mostra o seu modelo de dados, ou exemplo relevante.
long é diferente de long?, sendo que o primeiro não permite valores nulo e o segundo permite valor null. Quando for passar de um método ou algo parecido siga a lógica de exemplo:
public class Cliente {
private long? idade;
public long Idade()
{
if (idade.HasValue) return idade.Value;
return 0;
}
}
uma coisa é vc ter um valor default para um atributo caso ele não tenha valor definido, outra coisa é ele não ter valor definido ponto.
este exemplo considera idade sendo zero se ela for nulo ( que pode advir do fato da idade nula não ser sido preenchida quando criou-se o objeto ). Porém é mais facil ja inicializar o atributo com 0 E
algo como
public int X { get; set; } = 0; // C# 6.0 ou superior
se este não for o caso, então vamos com cuidado.
existe o conceito de coerção onde vc recebe um valor invalido mas tem uma regra para converte-lo para valido. no caso um setter poderia receber nulo ( por que isso pode ver de uma API legada, de um arquivo, sei la ) e transformar em 0 ou outro valor que faça sentido. isso vale a pena fazer no “setter” para que vc sempre armazene algo valido
existe o conceito de NullObject onde vc substitui o null daquela classe por algo que tem uma semantica parecida ao objeto que vc esta lidando podem ele não faz mal algum. nesse caso temos long e consideramos 0 pq, enfim, numeros. mas e se fosse um SeuTipo? ? Nesse caso talvez faça sentido vc ( em conjunto da solução 1 ) usar um SeuTipoNull que faz “nada” ( de novo, se fizer sentido ).
nada impede que vc lance uma exception “esta faltando a idade, moço”. talvez vc tem uma maquina de estados e num dado momento vc realmente não tem esta informação ( tipo vc fez cadastro, mas nao tem endereço ainda pq vai ser informado depois ) mas depois ela sera necessaria.
o uso de Nullable resolve alguns problemas. porem a semantica do nulo ou da ausencia do valor (não são a mesma coisa, mas em Java/C# isso se confunde – Perl 5 + Moose/Moo tem este conceito através do predicate/clearer por exemplo ) vai depender do meu modelo de dados. Como eu disse se fizer mais sentido um valor padrão, use-o. vai te trazer menos problema ( e codigo ).
por fim existe o conceito de performance ligado ai. se a cada vez que eu pego um valor eu preciso fazer algo como um if, uma conta, etc, então ele não é um getter. vc vai ter uma queda de desempenho se comparado a armazenar o valor pronto para retornar ( exceto em casos onde vc tem que retornar um clone/copia pois o objeto deve ser imutavel ).
enfim, meus 2 centavos sobre este desafio.
a abordagem do Dragoon não é ruim, eu só vejo as coisas de uma perspectiva diferente e ai somamos esforços para dar uma contribuição melhor.
Bom, o meu exemplo é de como trabalhar com um dado nullable, é apenas um exemplo, não analisei desempenho, não analise se a melhor opção seria trabalhar com long ( que não é a melhor forma, já visto que ninguém tem idade negativa e ninguém passa dos 200 anos, pelo menos atualmente nunca vi), o intuito era mostrar a forma básica de trabalhar com essa estrutura, onde tem métodos responsável em verificar se existe valor (diferente de nulo) e recuperar esse valor, o que achei estranho é o usuário usar ToString() isso me incomodou de mais por está causando ai sim um grande problema. Uma coisa que eu sempre digo recursos novos deve ser utilizados com cuidado então vai do tradicional mesmo sem utilizar = logo após get/set para setar um valor, é um recurso mas, ainda pouco utilizado nos códigos tradicionais, o legal é saber que existe claro +1 por isso, mas, o usuário não sabe utilizar ainda as estruturas básicas e passamos para ele subir a escada de 2 degraus a 2 degraus o correto seria 1 de cada vez.
Eu só uso esses tipos em raros casos (nullable), principalmente com classes que tenham relação com banco de dados, ao meu ver é uma mão na roda, diferente disso, nunca usaria long para um dado tão pequeno e nunca usaria nullable sem justificativa aparente.
Todo o código escrito deve ser analisado, mas, aqui muitas vezes pegamos o bonde andando e a duvida dele é menor ou maior do que está perguntando, talvez por trás de tudo isso tem um batalhão de código a verificar como está escrito.
A primeira resposta realmente eu na vida real, nunca faria, porque: pelo problema de tamanho de variável que acredito ser um exagero e isso compromete o desempenho na soma geral dos códigos e por usar um dado de um tipo fazendo a conversão para outro tipo, mas, como eu disse queria demostrar ao usuário a forma de verificar se o dado exite:
if (idade.HasValue)
e como recuperar
return idade.Value;
o dado que tem a estrutra nullable sendo utilizada.
Por isso o código ideal (ai que eu penso para mim é ideal, tem que ver o contexto da aplicação):
Código refatorado:
Da forma mais simples:
public class Cliente
{
public byte Idade { get; set; }
}
public class Cliente
{
public byte? Idade { get; set; }
}
Eu utilizaria byte aonde seu minimo é 0 e o máximo 255, exige menos espaço de memória e trabalha com get/set (podendo ser qualquer um dos exemplos) facilmente.
###Toda contribuição é válida e traz benefícios a comunidade.