2010-10-09 8 views
6

Duplique possibles:
Deep Null checking, is there a better way?
C# elegant way to check if a property's property is nullComment éviter de multiples si les contrôles null

je dois faire une recherche dans un modèle d'objet profond comme celui-ci:

p.OrganisationalUnit.Parent.Head.CurrentAllocation.Person; 

est là de toute façon pour évaluer cela et retourner null si o f la chaîne est nulle (OrganizationalUnit, parent, tête, etc.), sans avoir à faire un

if (p.org == null && p.org.Parent == null && p.org.Parent.Head . . .  
+0

Essayez d'éviter ce type de recherche; S'il vous plaît voir ma réponse ci-dessous pour plus de détails. – CesarGon

Répondre

8

Vous recherchez l'opérateur déréférence NULL-safe ?. (également connu sous le nom de navigation en toute sécurité) que certaines langues (par exemple Groovy), mais malheureusement, C# n'a pas cet opérateur.

Espérons qu'il sera mis en application un ....

jours

Voir aussi this post par Eric Lippert. La syntaxe qu'il propose est .?.

+0

Il est plus souvent appelé ** opérateur de propagation nul ** ou ** opérateur conditionnel nul **. –

+1

Il est maintenant disponible sur C# 6: https://msdn.microsoft.com/en-us/library/dn986595.aspx –

7

Avez-vous entendu parler du Law of Demeter?

Le chaînage de telles séquences d'appels n'est pas une bonne idée. Cela crée des dépendances terribles entre les classes dont vous n'avez pas besoin. Dans votre exemple, la classe contenant p devient dépendante de cinq autres classes. Je vous suggère de simplifier votre code et de faire en sorte que chaque classe vérifie les nullités à un seul niveau, dans leur propre contexte de connaissances.

+0

d'accord mais repris sur une base de code importante, ne peut pas refactoriser tout en un jour :) – leora

+0

@ooo: Je comprends. Dans ce cas, je pense que vous devez utiliser la chaîne laide des chèques nuls. J'essaierais de l'encapsuler dans une méthode privée afin que les dépendances soient isolées et facilement reconnaissables. – CesarGon

0

Pour répondre à la question dans votre titre, vous pouvez éviter en appliquant la « loi de Déméter » et la création d'une méthode appelée GetHeadOfParentOrganizationalUnit()

Je ne sais pas si la solution applique pour votre cas spécifique, mais cela vaut le coup d'oeil si vous pouvez éliminer toutes ces vérifications nuls.

Voir aussi: a link

+1

mais la fonction GetHeadofParent. .aurait juste cette même vérification nichée nichée – leora

+1

@oooo - Pas vraiment vous entrez dans un niveau à la fois. Chaque classe ne parle qu'à son collaborateur immédiat, vous ne tirez pas sur les internes du collaborateur pour arracher un état imbriqué ... * lire la loi de demeter *. De wikipedia - Un inconvénient de la loi de Demeter est qu'il faut parfois écrire un grand nombre de petites méthodes "wrapper" pour propager des appels de méthode aux composants. De plus, l'interface d'une classe peut devenir encombrante car elle héberge des méthodes pour des classes contenues, ce qui donne une classe sans interface cohésive. Mais cela pourrait aussi être un signe de mauvaise conception OO. – Gishu

6

Check out this article. Il présente une excellente solution qui vous permet d'écrire des choses comme ça:

p.With(x => x.OrganisationalUnit) 
.With(x => x.Parent) 
.With(x => x.Head) 
.With(x => x.CurrentAllocation 
.With(x => x.Person); 
-2

Vous pouvez utiliser la gestion des exceptions de base, ainsi que pour attraper. Je ne suis pas fou de cette solution, mais c'est une option. Si ces valeurs nulles imbriquées sont normales, les exceptions ne sont probablement pas la bonne réponse:

public class A 
{ 
} 
public class B 
{ 
    public A a; 
} 
public class C 
{ 
    public B b; 
} 
class Program 
{ 
    static A GetA(C c) 
    { 
     A myA; 
     try 
     { 
      myA = c.b.a; 
     } 
     catch 
     { 
      myA = null; 
     } 
     return myA; 
    }   

    static void Main(string[] args) 
    { 
     C theC = new C(); 
     theC.b = new B(); 
     theC.b.a = new A(); 
     A goodA = GetA(theC); 
     if (goodA != null) 
     { 
      Console.WriteLine("Expected nominal path."); 
     } 
     else 
     { 
      Console.WriteLine("Unexpected nominal path."); 
     } 
     theC.b.a = null; 
     A badA = GetA(theC); 
     if (badA == null) 
     { 
      Console.WriteLine("Expected off-nominal path."); 
     } 
     else 
     { 
      Console.WriteLine("Unexpected off-nominal path."); 
     } 

    } 

} 
+0

L'invocation du système de gestion des exceptions semble excessive pour les opérations normales; Cependant, comme vous l'avez dit, c'est une solution, sortir des sentiers battus. –

+0

@John K: Je suis d'accord - la seule façon dont j'aurais vraiment envisagé cela est de savoir si des nulls imbriqués représentaient un état "cassé". De plus, il y a le problème de ne pas savoir quel déréférencement a brisé le système, et la performance a été atteinte. Mais c'est un outil dans la boîte ... – PatrickV