2010-10-09 2 views
6

Возможные Duplicates:
Deep Null checking, is there a better way?
C# elegant way to check if a property's property is nullКак избежать мультипликатор, если нулевые чеки

я должен сделать поиск в глубокой объектной модели, как это:

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

есть все равно, чтобы оценить это и вернуть null, если есть o е цепь нулевая (OrganizationalUnit, родители, голова и т.д.), без необходимости делать

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

Старайтесь избегать такого поиска; см. мой ответ ниже для деталей. – CesarGon

ответ

8

Вы ищете нулевой безопасное разыменовывание оператор ?. (также известный как безопасную навигация), что некоторые языки (например, Groovy), но, к сожалению, у C# этого оператора нет.

Надеюсь, он будет реализован один день ....

Смотрите также this post Эрик Липперт. Синтаксис, который он предлагает, равен .?.

+0

Его чаще называют ** пустым оператором распространения ** или ** нулевым условным оператором **. –

+1

Теперь он доступен на C# 6: https://msdn.microsoft.com/en-us/library/dn986595.aspx –

7

Слышали ли вы о Law of Demeter?

Цепочка таких длинных последовательностей вызовов - не очень хорошая идея. Это создает ужасные зависимости между классами, которые вам не нужны.

В вашем примере класс, содержащий p, становится зависимым от пять других классов. Я предлагаю вам упростить свой код и сделать каждую проверку класса для нулей на одном уровне в своем собственном контексте знаний.

+0

согласен, но берет на себя большую базу кода, не может реорганизовать все за один день :) – leora

+0

@ooo: Я понимаю. В этом случае, я думаю, вам нужно использовать уродливую цепочку нулевых проверок. Я бы попытался инкапсулировать это в частный метод, чтобы зависимости были изолированы и легко узнаваемы. – CesarGon

0

Чтобы ответить на этот вопрос в заголовке, вы можете избежать, применив «закон Деметры» и создание метода, называемого GetHeadOfParentOrganizationalUnit()

я не уверен, если решение применяется для вашего конкретного случая, но это стоит посмотреть, если вы можете устранить все эти нулевые проверки.

Смотрите также: a link

+1

, но затем функция GetHeadofParent. ,имел бы только ту же самую вложенную нулевую проверку – leora

+1

@oooo - Не совсем вы шаг за шагом на одном уровне за раз. Каждый класс говорит только о своем непосредственном сотруднике, вы не взламываете внутренности, чтобы соратник отрывал какое-то вложенное состояние ... * читал закон о демерете *. Из википедии. Недостатком Закона Деметры является то, что иногда требуется написание большого количества небольших «оберточных» методов для распространения вызовов методов на компоненты. Кроме того, интерфейс класса может стать громоздким, поскольку он содержит методы для содержащихся классов, что приводит к классу без сплоченного интерфейса. Но это также может быть признаком плохого дизайна OO. – Gishu

6

Отъезд this article. Это отличное решение, которое позволяет вам писать такие вещи:

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

Вы также можете использовать базовую обработку исключений, чтобы поймать это. Я не сумасшедший об этом решении, но это вариант. Если эти вложенные нули являются нормальной работой, исключения, вероятно, являются неправильным ответом:

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

Вызов системы обработки исключений кажется чрезмерным для обычных операций; однако, как вы сказали, это решение, думая нестандартно. –

+0

@John K: Я согласен - единственный способ, который я когда-либо рассматривал, - это если любые вложенные нули представляли «разбитое» состояние. Плюс проблема в том, что не зная, какая развязка нарушила систему, и производительность попала. Но это инструмент в коробке ... – PatrickV

Смежные вопросы