【问题标题】:C# null check chain in method call方法调用中的 C# null 检查链
【发布时间】:2017-08-25 04:29:29
【问题描述】:

我想下面是方法调用链。

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

【问题讨论】:

标签: c# null-check


【解决方案1】:

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

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

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

【讨论】:

  • 对不起。我是 Unity Engine 的游戏程序员。它仍然使用 Mono v2.6。
【解决方案2】:

你可以的

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

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

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

【讨论】:

  • 很遗憾我的开发环境是C# 3.0。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

    那么,假设您(或其他人)不能使用空条件运算符,是否有充分的理由使用这种创建对象的方法模式而不是创建对象的构造函数?构造函数保证不返回 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();
    }
    

    【讨论】:

    • 我希望这是关于这种特殊情况的陈述,而不是关于设计模式有用性的一般陈述。
    • 您是否有充分的理由不使用保证不为空的构造函数?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-07
    相关资源
    最近更新 更多