С# null цепочка проверки в вызове метода

Я предполагаю, что цепочка вызовов метода ниже.

void DoSomething()
{
    ObjectA a = CreateA();
    if (a != null)
    {
        a.Foo();
    }
}

ObjectA CreateA()
{
    ObjectB b = CreateB();
    if (b != null)
    {    
        ObjectA a = b.ToA();
        return a;
    }
    return null;
}

Если глубина вызова метода будет глубже, проверка нуля будет более наложенной. Есть ли хорошее решение для этого?

Modified

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

void SetImage()
{
    UISprite image = GetSprite();
    if (image  != null)
    {
        image.spriteName = "hat";
    }
}

UISprite GetSprite()
{
    UISprite image = GetComponent<UISprite>();
    if (image  != null)
    {   
        image.width = 100;
        image.height = 100;
        return image;
    }
    return null;
}
+3
источник поделиться
4 ответа

Начиная с С# 6.0 вы можете использовать Null-Conditional Operator, который позволяет делать нечетные проверки:

var result = possiblyNull?.MethodThatCanReturnNull()?.SomeProperty;

Эта конструкция создаст результат null, если любой элемент в цепочке произведет null.

+6
источник

Вы можете сделать

void DoSomething()
{
    CreateA()?.Foo();
}

ObjectA CreateA()
{
    return CreateB()?.ToA();
}

Ваш другой подход, если вы не можете использовать С# 6, не возвращает nulls, использует пустые объекты таким образом, чтобы вам никогда не приходилось иметь дело с нулевой проверкой (но вы все еще можете проверить, является ли что-то нулевым объектом)

+2
источник

Если вы используете С# 6.0 или выше, у вас есть простое решение с условными операторами Null для этой проблемы.

см. эту ссылку

https://msdn.microsoft.com/en-au/library/dn986595.aspx?f=255&MSPPError=-2147217396&cs-save-lang=1&cs-lang=csharp#code-snippet-1

0
источник

Итак, если вы (или кто-то еще) не можете использовать оператор с нулевым условием, есть ли веская причина использовать этот шаблон методов, создающих объекты вместо конструкторов, создающих объекты? Конструкторы гарантированно не возвращают null.

Похоже, что у вас есть конверсия или иерархия вложенных объектов, но нет наследственной иерархии, где вы могли бы просто вернуться к полиморфизму. Может быть, инструмент, такой как AutoMapper, может быть полезен для последовательного кодирования этих методов ToX()?

Я не уверен, как это было бы "вложенным". Ваш метод CreateB() будет выглядеть точно так же, как ваш код CreateA(). Вы не получите в итоге "пирамиды" всего лишь много одинаковых методов.

ObjectB CreateB()
    {
        ObjectC c = CreateC();
        if (c != null)
        {    
            ObjectB b = c.ToB();
            return b;
        }
        return null;
    }

В большинстве случаев вы делаете это в среде, где вы не контролируете все классы. В этом случае наилучшим подходом является написание собственных функций преобразования или AutoMapper (действительно, стоит того времени). Но, если у вас есть иерархия классов, вы можете реализовать абстрактный класс, который сделает большую часть тяжелой работы для вас. Но, честно говоря, я бы написал только что-то подобное, если бы у меня была действительно веская причина (что-то большее, чем просто хотелось трахаться с людьми). Я включаю это, чтобы продемонстрировать, насколько проще жизнь, если вы просто используете конструктор, который гарантированно не возвращает null;

public abstract class MyAbstractObject<Tobj> where TObj: MyAbstractObject, new()
{
    public static MyAbstractObject CreateObject()
    {
        Tobj subOb = new TObj();
        MyAbstractObject parent = subOb.ToObject();
        return parent;
    }
    public virtual TObj ToObject()
    {
        return CreateObject();
    }
}

public class ObjectD : MyAbstractObject<ObjectC> { }
public class ObjectC : MyAbstractObject<ObjectB> { }
public class ObjectB : MyAbstractObject<ObjectA> { }
public class ObjectA : MyAbstractObject<ObjectA>
{
    public override TObj ToObject()
    {
        return this;
    }
}

static void Main()
{
    ObjectA a = ObjectD.CreateObject();
}
0
источник

Посмотрите другие вопросы по меткам или Задайте вопрос