C# null check chain in method call

2020-04-11 13:23发布

I suppose method call chain below.

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

If method call depth get deeper, null checking will be more overlapped. Is there any good solution for this?

Modified

I changed example code. It can't solve my problem that change CreateA to constructor. The problem is only unnecessary null check chaining overlapping.

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
4条回答
一纸荒年 Trace。
2楼-- · 2020-04-11 13:42

Starting with C# 6.0 you can use Null-Conditional Operator, which lets you make null-checking implicitly:

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

This construct will produce a null result if any element in the chain produces null.

查看更多
虎瘦雄心在
3楼-- · 2020-04-11 13:45

You can do

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

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

Your other approach if you can't use C# 6, is don't return nulls, use null objects that way you never have to deal with null checking ( but you can still check if something is the null object )

查看更多
放我归山
4楼-- · 2020-04-11 13:58

If you are using C# 6.0 or higher, you got an easy solution with Null conditional operators for this issue.

see this link

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

查看更多
够拽才男人
5楼-- · 2020-04-11 14:08

So, assuming you (or someone else) can't use the null-conditional operator, is there a good reason to be using this pattern of methods creating objects instead of constructors creating the objects? Constructors are guaranteed not to return null.

It looks like you have some conversion or nested object heirarchy, but no inheritance heirarchy where you could just fall back on polymorphism. Maybe a tool like AutoMapper could be useful to encode these ToX() methods in a consistent manner?

I'm not sure how "nested" this would be. Your CreateB() method is going to look exactly like your CreateA() code. You're not going to end up with a "pyramid," just a lot of identical methods.

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

Most of the time, you're doing this in an environment where you don't control all the classes. In that case, writing your own conversion functions or AutoMapper (really, worth the time) is the best approach. But, if you own the class hierarchy you might implement an abstract class that will do most of the heavy lifting for you. But honestly, I would only write something like this if I had a really good reason (something more than I just wanted to fuck with people). I include this to demonstrate how much simpler life is if you just use a constructor, which is guaranteed not to return 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();
}
查看更多
登录 后发表回答