3

我想下面的方法调用链。

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;
}

如果方法调用深度越深,空值检查就会越重叠。有什么好的解决方案吗?

修改的

我更改了示例代码。将 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;
}
4

4 回答 4

12

从 C# 6.0 开始,您可以使用Null-Conditional Operator,它可以让您隐式地进行 null 检查:

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

null如果链中的任何元素产生 ,则此构造将产生结果null

于 2017-03-31T02:53:13.483 回答
2

你可以做

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

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

如果你不能使用 C# 6,你的另一种方法是不要返回空值,使用空对象,这样你就不必处理空值检查(但你仍然可以检查是否有空对象)

于 2017-03-31T02:59:28.520 回答
0

如果您使用的是 C# 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

于 2017-03-31T03:11:27.800 回答
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();
}
于 2017-03-31T03:56:35.473 回答