消除LINQ深层结构中的IF检查

时间:2014-08-13 17:20:36

标签: c# xml linq if-statement null

我想使用XDocument访问XML文档中的一些深层结构。

为了避免NULL异常,所以我有很多IF检查,如

if(doc.Root.Element("E1") != null)
{
    if(doc.Root.Element("E1").Element("E2") != null)
    { 
        if(doc.Root.Element("E1")
                   .Element("E2")
                   .SingleOrDefault(e => e.Attribute("id") != null && 
                                         e.Attribute("id").Equals("ABC")) != null)
        {
             var n = doc.Root
                        .Element("E1")
                        .Element("E2")
                        .SingleOrDefault(e => e.Attribute("id") != null && 
                                              e.Attribute("id").Equals("ABC"))
                        .Attribute("name").Value;
        }
    }
}

实际结构更深入。我可以以某种方式消除这些NULL检查吗?

3 个答案:

答案 0 :(得分:1)

您可以创建一个简单的扩展方法,该方法能够将投影应用于传播空值而不是抛出异常的可能为空的值:(请注意,不同的人喜欢为此操作使用不同的名称;随意调用方法对你来说最有意义。)

public static TResult Use<TSource, TResult>(
    this TSource obj, Func<TSource, TResult> selector)
    where TSource : class
    where TResult : class
{
    return obj == null ? null : selector(obj);
}

有了这个,您的代码可以压缩成以下内容:

var name = doc.Root.Element("E1")
        .Use(element => element.Elements("E2"))
        .Use(elements => elements.SingleOrDefault(
            element => element.Attribute("id")
                .Use(att => att.Value) == "ABC"))
        .Use(element => element.Attribute("name").Value);

答案 1 :(得分:-1)

您不需要任何支票。您可以将属性转换为string,然后使用==检查相等性,而不是使用Equals

对于元素,您可以使用XPath而不是像Root.Element("Foo").Element("Bar")等单独选择它们。然后只检查XPath查询的结果。这将需要 less < / em>至少检查......

另外值得注意的是,在C# 6中会有一个Null propagating operator并允许您安全地访问对象的成员,然后您不需要任何这些检查。

答案 2 :(得分:-2)

你可以这样做:

            var n = doc.Elements("E1").DefaultIfEmpty()
                    .Elements("E2").DefaultIfEmpty()
                    .FirstOrDefault(e => e!= null && e.Attribute("id") != null && e.Attribute("id").Equals("ABC"));

        if (n != null) {
            string s = n.Attribute("name").Value;
        }