A melhor maneira de se lidar com referências nulas em uma hierarquia de objetos
-
09-09-2019 - |
Pergunta
Eu estou procurando uma boa maneira de lidar com uma referência nula na hierarquia de objetos.
ou seja:
if(null == Object1.Object2.Object3.Property)
Este exemplo irá lançar uma exceção Null Reference se digamos Object2 é nulo.
No meu caso eu não me importo o que é nula, assim que algo é. Eu realmente não quero colocar try / capturas em torno de cada lugar que eu quero fazer algo como isso, então eu estive procurando uma alternativa.
Eu experimentei com o ?? operador, mas este faz para algum código olhando feio após dois níveis.
Todas as idéias apreciado.
Solução
Agora, isso pode ser pela tangente ... mas eu sugiro uma alteração de design para evitar a feiúra e dor
Chamando Object1.Object2.Object3.Property
viola a lei de Deméter . Em vez disso, se você está supostamente para obter a essa propriedade, Object1 deve expor uma propriedade em si ... Então você deve estar chamando Object1.RetrievedFromTheDepthsProperty
Por isso é necessário .. é que, se o designer do Tipo Object2 muda o tipo de objeto retornado pela 'object3' campo / propriedade para aquele que não tem a propriedade que você está procurando, você pode ser metralhado. O cliente sabe muito sobre a estrutura interna do Object1. Se Object1 encapsulado, onde os dados estão localizados internamente, você estaria seguro contra mudanças futuras. Também esta propriedade pode fazer tudo o nulo verificar internamente como necessário ... deixando-o com o muito mais limpo
if (Object1.RetrievedFromTheDepthsProperty == null) {...}
Outras dicas
Este (dereferencing nulo-safe) é algo que começa levantado ocasionalmente, e não; não existe uma resposta arrumada no momento, com excepção:
if(Object1 == null || Object1.Object2 == null
|| Object1.Object2.Object3 == null
|| Object1.Object2.Object3.Property == null)
Você pode fazer alguns cache menor se você precisa (através da introdução de variáveis), mas que fica ainda mais feia:
SomeType2 obj2;
SomeType3 obj3;
if(Object1 == null || (obj2 = Object1.Object2) == null
|| (obj3 = obj2.Object3) == null
|| obj3.Property == null)
Em geral, gostaria de aconselhar contra o acima, a menos que você realmente, realmente não quero chamar uma propriedade duas vezes (porque ele faz mais trabalho do que uma propriedade deve)
Você pode usar o objeto nulo objeto padrão .
class Car {
Engine engine = null;
public Engine Engine {
get {
return engine ?? new NullEngine();
}
}
}
class Engine {
string make;
public virtual string Make { get { return make; } }
}
class NullEngine : Engine {
public override string Make { get { return null; } }
}
Em seguida, você poderia fazer:
Car car;
if (car.Engine.Make != null) Console.WriteLine(car.Engine.Make);
Em vez de:
Car car;
if (car.Engine != null && car.Engine.Make != null) Console.WriteLine(car.Engine.Make);
Note que é bastante um monte de trabalho para definir "objetos nulos" para todo o seu modelo. Você também precisa tomar muito cuidado para que você não confundir os usuários de seu modelo. Código tendem a explodir rapidamente se você passar null ao redor e se esqueça de verificar para isso, mas um "objeto nulo" pode mais fácil sobreviver profundamente na pilha de chamadas e causar problemas sutis, uma vez que não é um objeto real.
Não responder diretamente sua pergunta - apenas algumas dicas:
- Null objeto
- ele só não parece adequado para percorrer a hierarquia até aqui (seus três níveis), talvez algum método no primeiro segundo nível / que iria responder a condição ajudaria
Em geral, se você não se importa qual a propriedade foi nula em sua hierarquia de objetos simplesmente não fazer prova contra ele. Use um manipulador de erro global para a aplicação (isso vai depender do tipo de aplicação ASP.NET, WinForms, ...) e dizer ao usuário algo deu errado.
Eu sugerem fortemente que você olhar para a seguinte mensagem: http://www.hardcodet.net/2008/ 12 / observar-dependências-through-lambda-expressions-part1
Trata-se de um problema semelhante, e também permite que você manipule facilmente as alterações.