C# 如何分离多个级别的成员访问权限
假设我定义了这些虚拟类:C# 如何分离多个级别的成员访问权限,c#,linq,C#,Linq,假设我定义了这些虚拟类: public class MyObject { public InterestingFact InterestingFact { get; set; } } public class InterestingFact { public Detail Detail { get; set; } } public class Detail { public string Information { get; set; } } 我还有一个MyObject
public class MyObject
{
public InterestingFact InterestingFact { get; set; }
}
public class InterestingFact
{
public Detail Detail { get; set; }
}
public class Detail
{
public string Information { get; set; }
}
我还有一个MyObject
的实例:
var obj = new MyObject() { InterestingFact = new InterestingFact() };
如果我想尝试访问信息
属性,我可以执行以下操作:
string info = null;
if (obj != null
&& obj.InterestingFact != null
&& obj.InterestingFact.Detail != null)
{
info = obj.InterestingFact.Detail.Information;
}
// Here I should still have a null of type string.
var info = obj.NullOr(o => o.InterestingFact.Detail.Information);
为了讨论这个问题,忽略德米特定律,这并不是每次我想进入我所拥有的物体深处的东西时都有很多乐趣。当然,我可以创建一个扩展方法:
public static U NullOr<T, U>(this T target, Func<T, U> selector)
{
if (EqualityComparer<T>.Default.Equals(target, default(T)))
{
return default(U);
}
return selector(target);
}
不过,这仍然有点冗长。理想情况下,我想做更多类似的事情:
string info = null;
if (obj != null
&& obj.InterestingFact != null
&& obj.InterestingFact.Detail != null)
{
info = obj.InterestingFact.Detail.Information;
}
// Here I should still have a null of type string.
var info = obj.NullOr(o => o.InterestingFact.Detail.Information);
我从未使用过Expression
s;如果我在NullOr
中使用表达式而不是Func
,那么在我看来它是一个成员访问,而不是三个成员访问。有没有办法达到上述目的,或者这个公式是遥不可及的
(当然,上一个公式还有一个问题,即发送的表达式可能不仅仅是链式成员访问…)关于使用扩展方法实现所需结果的最简单方法,如下所示
public static class ExtensionMethods
{
public static TR DefaultIfNull<T, TR>(this T source, Expression<Func<T, TR>> expr, TR defaultValue = default(TR))
{
TR result = defaultValue;
try
{
result = expr.Compile().Invoke(source);
}
catch (NullReferenceException)
{
// DO NOTHING
}
return result;
}
}
请注意,这不是最佳解决方案,因为它不会检查单个表达式节点是否为null,因此如果树中的任何节点碰巧在内部生成NullReferenceException
,则将返回默认值,而不是抛出异常。但是,对于一般和简单的使用,这可能是最佳的解决方案(主要是为了简单)。这是对C#的一个补充,使用?。
运算符,但尚未将其应用到语言中。Mads说他们正在认真考虑,所以有一天你可能会写出obj?.InterestingFact?.Detail?.Information
。在那之前,你这样做是我所知道的唯一的方法。@MosheKatz:我看到了,我真希望我能通过操作符重载来完成。可能是@MosheKatz:的副本,谢谢!我不知道我怎么会错过这一点。我还应该注意到,使用表达式树解析器实际上没有任何好处。通过直接调用Func,您可以进一步简化上面的代码。