具有父空值的变量分辨率
本文关键字:变量 分辨率 空值 | 更新日期: 2023-09-27 18:13:48
我有一个方法,它有很多像这样的语句:
employee.LastName = file.EMPLOYEE.NAME.SUBNAME.FAMILYNAME.NAMEPART1.Value;
(这是一个合成结构。实际的结构基于2.3 HL7 XML,要复杂得多,并且充满了无意义的对象。)
所以我的问题是这些值中的任何一个都可以为空。如果我不检查,那么当我试图获得链中的下一个值时,它将抛出异常。
显然我可以这样做:
if (contract.EMPLOYEE != null)
if (contract.EMPLOYEE.NAME.SUBNAME != null)
if (contract.EMPLOYEE.NAME.FAMILYNAME != null)
if (contract.EMPLOYEE.NAME.FAMILYNAME.NAMEPART1 != null)
employee.LastName = file.EMPLOYEE.NAME.SUBNAME.FAMILYNAME.NAMEPART1.Value;
但是每次我需要设置一个值时都要检查很多次。(并且对象树变化很大,所以我不能做一次检查,然后完成系统。)
也许更好的方法是这样做:
try
{
employee.LastName = file.EMPLOYEE.NAME.SUBNAME.FAMILYNAME.NAMEPART1.Value;
}
catch
{}
(注意,如果值不存在,那么我可以不做任何事情。)
然而,这仍然有点混乱。在这个方法中,我有14项要设置,还有更多的要设置。
是否有一种方法可以将它抽象出来,这样我就可以只做setter和其他一些东西了?
我想到了一个方法调用,可以执行检查/尝试语句,但是如果我传递file.EMPLOYEE.NAME.SUBNAME.FAMILYNAME.NAMEPART1.Value
,它将在我传递它时尝试解决它(从而给我一个异常)。
有别的(干净的)方法吗?(也许扩展方法会起作用?)如有任何建议,我将不胜感激。
注意:最后我对每一行都这样做:
try { employee.LastName = file.EMPLOYEE.NAME.SUBNAME.FAMILYNAME.NAMEPART1.Value; } catch (System.NullReferenceException) { }
这个怎么样:
static class Coalesce
{
static public TResult C<T, TResult>(this T obj, Func<T, TResult> func)
where TResult : class
{
if (obj != null)
return func(obj);
return null;
}
}
像这样使用:
employee.LastName =
file.C(o => o.EMPLOYEE)
.C(o => o.NAME)
.C(o => o.SUBNAME)
.C(o => o.FAMILYNAME)
.C(o => o.NAMEPART1)
.C(o => o.Value);
如果链中的任何属性为空,则返回null。
这是受到扩展c#合并操作符的问题的启发,但我使用了一种稍微不同的方法。以稍微长一点的调用语法为代价,我的扩展类更简单,并且对链中的链接数量没有限制。
也可以与??赋值默认值的操作符:
class Foo { public Bar MyBar { get; } }
class Bar { public Baz MyBaz { get; } }
class Baz { }
Baz baz = foo.C(o => o.MyBar).C(o => o.MyBaz) ?? new Baz();