2010-10-09 8 views
6

posibles duplicados:
Deep Null checking, is there a better way?
C# elegant way to check if a property's property is nullCómo evitar la multiplicidad de si los cheques nulos

que tengo que hacer una búsqueda en un modelo de objetos profunda como esta:

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

hay alguna forma de evalute esto y devolver null si alguno o f la cadena es nula (OrganizationalUnit, padre, cabeza, etc.), sin tener que hacer un

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

Trate de evitar ese tipo de búsqueda; por favor vea mi respuesta a continuación para más detalles. – CesarGon

Respuesta

8

Usted está buscando el operador de eliminar la referencia nula de fallos ?. (también conocida como la navegación segura) que algunos idiomas (por ejemplo, Groovy) tienen, pero desafortunadamente C# no tiene este operador.

Es de esperar que se aplicaron una día ....

Ver también this post por Eric Lippert. La sintaxis que propone es .?.

+0

Se denomina con más frecuencia ** operador de propagación nulo ** o ** operador condicional nulo **. –

+1

Ahora está disponible en C# 6: https://msdn.microsoft.com/en-us/library/dn986595.aspx –

7

¿Has oído hablar del Law of Demeter?

encadenamiento de tales secuencias largas de las llamadas no es una buena idea. Crea espantosas dependencias entre clases que no necesita.

En su ejemplo, la clase que contiene p se vuelve dependiente de otras otras clases. Sugiero que simplifique su código y haga que cada clase verifique nulos en un solo nivel, en su propio contexto de conocimiento.

+0

de acuerdo pero apoderado de una gran base de código, no puede refactorizar todo en un día :) – leora

+0

@ooo: lo entiendo. En ese caso, creo que debes usar la fea cadena de verificaciones nulas. Trataría de encapsular esto en un método privado para que las dependencias estén aisladas y sean fácilmente reconocibles. – CesarGon

0

Para responder a la pregunta en su título, se puede evitar mediante la aplicación de la 'ley del Demeter' y la creación de un método llamado GetHeadOfParentOrganizationalUnit()

No estoy seguro de si la solución se aplica para su caso específico, pero vale la pena ver si puede eliminar todos esos controles nulos.

Consulte también: a link

+1

pero luego la función GetHeadofParent. .solo tendría esa misma verificación nula anidada – leora

+1

@oooo - En realidad, no se da un paso en un nivel a la vez. Cada clase solo habla con su colaborador inmediato, usted no piratea en el interior del colaborador para arrancar algún estado anidado ... * lea sobre la ley de demeter *. De wikipedia - Una desventaja de la Ley de Demeter es que a veces requiere escribir una gran cantidad de pequeños métodos de "envoltura" para propagar llamadas de método a los componentes. Además, la interfaz de una clase puede volverse voluminosa ya que aloja métodos para clases contenidas, lo que da como resultado una clase sin una interfaz cohesiva. Pero esto también podría ser un signo de mal diseño OO. – Gishu

6

Salida this article. Presenta una gran solución que le permite escribir cosas como esas:

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

También puede usar el manejo básico de excepciones para captar eso. No estoy loco por esa solución, pero es una opción. Si estos nulos anidados son operación normal, las excepciones probablemente no sean la respuesta correcta:

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

Invocar el sistema de manejo de excepciones parece excesivo para las operaciones normales; sin embargo, como dijiste, es una solución, pensar fuera de la caja. –

+0

@John K: Estoy de acuerdo, la única forma en que realmente lo consideraría es si alguno de los nulos anidados representaba un estado "roto". Además, está el problema de no saber qué desreferencia rompió el sistema y el rendimiento. Pero es una herramienta en la caja ... – PatrickV

Cuestiones relacionadas