如何在深层lamda表达式中检查空值?
比方说,我有一个嵌套了几层深度的类结构,我想执行以下lambda:
x => x.Two.Three.Four.Foo
Run Code Online (Sandbox Code Playgroud)
如果Two,Three或Four为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; }
}
}
Run Code Online (Sandbox Code Playgroud)
更新:
一种解决方案是捕获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;
}
Run Code Online (Sandbox Code Playgroud)
但是我不愿意承担捕捉异常的费用,在我看来,异常并不是特别的.我希望在我的域名中经常出现这种情况.
更新2:
另一个解决方案是修改属性getter,如下所示:
public class One
{
private Two two;
public Two Two
{
get
{
return two ?? new Two();
}
set
{
two = value;
}
}
}
Run Code Online (Sandbox Code Playgroud)
哪个对我的域名来说是好的,但有时候我真的期望一个属性返回null.我检查了Josh E的答案是有帮助的,因为它在某些情况下非常接近我需要的.
Luc*_*ero 17
您可以使用通用帮助程序扩展方法执行此操作,例如:
public static class Get {
public static T IfNotNull<T, U>(this U item, Func<U, T> lambda) where U: class {
if (item == null) {
return default(T);
}
return lambda(item);
}
}
var one = new One();
string fooIfNotNull = one.IfNotNull(x => x.Two).IfNotNull(x => x.Three).IfNotNull(x => x.Four).IfNotNull(x => x.Foo);
Run Code Online (Sandbox Code Playgroud)
Gab*_*art 13
你不能以简洁的方式做到这一点.您可以使lambda多行,或使用嵌套的三元运算符:
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;
Run Code Online (Sandbox Code Playgroud)
丑陋,我知道.
| 归档时间: |
|
| 查看次数: |
19479 次 |
| 最近记录: |