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.

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top