【发布时间】:2009-05-12 20:01:21
【问题描述】:
如何检查深层 lamda 表达式中的空值?
例如,我有一个嵌套了好几层的类结构,我想执行以下 lambda:
x => x.Two.Three.Four.Foo
如果二、三或四为 null,我希望它返回 null,而不是抛出 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:
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;
}
但我不想承担捕获在我看来并不例外的异常的费用。我希望在我的域中经常出现这种情况。
更新 2:
另一种解决方案是像这样修改属性获取器:
public class One
{
private Two two;
public Two Two
{
get
{
return two ?? new Two();
}
set
{
two = value;
}
}
}
这对我的域来说基本没问题,但有时我真的希望属性返回 null。我检查了 Josh E 的回答,认为它很有帮助,因为它在某些情况下非常接近我的需要。
【问题讨论】: