Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何分离多个级别的成员访问权限_C#_Linq - Fatal编程技术网

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,您可以进一步简化上面的代码。