如何检查深度 lambda 表达式中的空值? [英] How to check for nulls in a deep lambda expression?

查看:56
本文介绍了如何检查深度 lambda 表达式中的空值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在深度 lamda 表达式中检查空值?

How can I check for nulls in a deep lamda expression?

例如,我有一个嵌套多层的类结构,我想执行以下 lambda:

Say for example I have a class structure that was nested several layers deep, and I wanted to execute the following lambda:

x => x.Two.Three.Four.Foo

如果两个、三个或四个为 null,我希望它返回 null,而不是抛出 System.NullReferenceException.

I want it to return null if Two, Three, or Four were null, rather than throwing a System.NullReferenceException.

public class Tests
{
    // This test will succeed
    [Fact]
    public void ReturnsValueWhenClass2NotNull()
    {
        var one = new One();
        one.Two = new Two();
        one.Two.Three = new Three();
        one.Two.Three.Four = new Four();
        one.Two.Three.Four.Foo = "blah";

        var result = GetValue(one, x => x.Two.Three.Four.Foo);

        Assert.Equal("blah", result);
    }

    // This test will fail
    [Fact]
    public void ReturnsNullWhenClass2IsNull()
    {
        var one = new One();

        var result = GetValue(one, x => x.Two.Three.Four.Foo);

        Assert.Equal(null, result);
    }

    private TResult GetValue<TModel, TResult>(TModel model, Expression<Func<TModel, TResult>> expression)
    {
        var func = expression.Compile();
        var value = func(model);
        return value;
    }

    public class One
    {
        public Two Two { get; set; }
    }

    public class Two
    {
        public Three Three { get; set; }
    }

    public class Three
    {
        public Four Four { get; set; }
    }

    public class Four
    {
        public string Foo { get; set; }
        public string Bar { get; set; }
    }
}

更新:

一种解决方案是像这样捕获 NullReferenceException:

One solution would be to catch the NullReferenceException like this:

    private TResult GetValue<TModel, TResult>(TModel model, Expression<Func<TModel, TResult>> expression)
    {
        TResult value;
        try
        {
            var func = expression.Compile();
            value = func(model);
        }
        catch (NullReferenceException)
        {
            value = default(TResult);
        }
        return value;
    }

但我讨厌为捕获在我看来并不特殊的异常而付出代价.我希望在我的域中经常出现这种情况.

But I hate to incur the expense of catching an exception that is not, in my mind, exceptional. I expect this to be the case quite often in my domain.

更新 2:

另一种解决方案是像这样修改属性 getter:

Another solution would be modify the property getters like this:

    public class One
    {
        private Two two;
        public Two Two
        {
            get
            {
                return two ?? new Two();
            }
            set
            {
                two = value;
            }
        }
    }

这对我的域来说基本没问题,但有时我真的希望属性返回 null.我检查了 Josh E 的回答很有帮助,因为它在某些情况下非常接近我所需要的.

Which is mostly ok for my domain, but there are times when I really to expect a property to return null. I checked the answer from Josh E as helpful since it comes pretty close to what I need in some cases.

推荐答案

你不能以简洁的方式做到这一点.您可以使 lambda 多行,也可以使用嵌套的三元运算符:

You can't do that in a concise way. You can either make the lambda multiple lines, or use nested ternary operators:

var result = GetValue(one, x => x.Two == null ? null :
                                x.Two.Three == null ? null :
                                x.Two.Three.Four == null ? null :
                                x.Two.Three.Four.Foo;

丑,我知道.

这篇关于如何检查深度 lambda 表达式中的空值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆