Atualização: a partir do Visual Studio 2015, o compilador C # (versão 6 do idioma) agora reconhece o ?.
operador, o que facilita a "verificação nula profunda". Veja esta resposta para detalhes.
Além de redesenhar seu código, como
sugeriu esta resposta excluída , outra opção (ainda que terrível) seria usar um try…catch
bloco para verificar se isso NullReferenceException
ocorre em algum momento durante essa pesquisa profunda de propriedade.
try
{
var x = cake.frosting.berries.loader;
...
}
catch (NullReferenceException ex)
{
// either one of cake, frosting, or berries was null
...
}
Eu pessoalmente não faria isso pelos seguintes motivos:
- Não parece legal.
- Ele usa tratamento de exceção, que deve visar situações excepcionais e não algo que você espera que ocorra frequentemente durante o curso normal da operação.
NullReferenceException
Provavelmente, nunca deve ser capturado explicitamente. (Veja esta pergunta .)
Então, é possível usar algum método de extensão ou seria um recurso de linguagem, [...]
Isso seria quase certamente tem que ser um recurso de linguagem (que está disponível em C # 6 na forma do .?
e ?[]
operadores), a menos que C # já teve avaliação preguiçosa mais sofisticado, ou menos que você queira usar a reflexão (que provavelmente também não é uma boa ideia por razões de desempenho e segurança do tipo).
Como não há como simplesmente passar cake.frosting.berries.loader
para uma função (ela seria avaliada e lançaria uma exceção de referência nula), você teria que implementar um método de pesquisa geral da seguinte maneira: Ele pega objetos e nomes de propriedades para olho para cima:
static object LookupProperty( object startingPoint, params string[] lookupChain )
{
// 1. if 'startingPoint' is null, return null, or throw an exception.
// 2. recursively look up one property/field after the other from 'lookupChain',
// using reflection.
// 3. if one lookup is not possible, return null, or throw an exception.
// 3. return the last property/field's value.
}
...
var x = LookupProperty( cake, "frosting", "berries", "loader" );
(Nota: código editado.)
Você vê rapidamente vários problemas com essa abordagem. Primeiro, você não obtém nenhum tipo de segurança e possível boxe de valores de propriedades de um tipo simples. Segundo, você pode retornar null
se algo der errado e terá que verificar isso em sua função de chamada ou lançar uma exceção e voltar ao ponto em que começou. Terceiro, pode ser lento. Quarto, parece mais feio do que você começou.
[...] ou é apenas uma má ideia?
Eu ficaria com:
if (cake != null && cake.frosting != null && ...) ...
ou vá com a resposta acima de Mehrdad Afshari.
PS: Quando escrevi esta resposta, obviamente não considerava árvores de expressão para funções lambda; veja, por exemplo, a resposta do @driis 'para uma solução nessa direção. Também é baseado em um tipo de reflexão e, portanto, pode não ter um desempenho tão bom quanto em uma solução mais simples ( if (… != null & … != null) …
), mas pode ser considerado melhor do ponto de vista da sintaxe.