你如何防范Linq To Xml中的空引用异常?

kit*_*une 12 xml linq exception-handling linq-to-xml

<?xml version="1.0" encoding="utf-8" ?>
<pages> 
  <page id="56">
    <img id="teaser" src="img/teaser_company.png"></img>
  </page>  
</pages>
Run Code Online (Sandbox Code Playgroud)

我有一个xml文件,它定义了cms中页面的附加资源.使用LinqToXml查询此文件时,保护Null Reference异常的最佳方法是什么?

var page = (from tabElement in extensionsDoc.Descendants("page")
where tabElement.Attribute("id").Value == tabId.ToString()
select tabElement).SingleOrDefault();
Run Code Online (Sandbox Code Playgroud)

如果页面元素没有名为"id"的属性,则此代码可能会触发Null Reference异常.我是否必须使用try catch块或有办法处理这个问题?例如,如果页面元素没有名为"id"的属性,则为页面对象返回null.

Jon*_*eet 28

编辑:这是很久以前写的 - 这些天我肯定会按照伊戈尔的回答去演员.

最简单的方法是:

var page = (from tabElement in extensionsDoc.Descendants("page")
            let idAttribute = tabElement.Attribute("id")
            where idAttribute != null 
                  && idAttribute.Value == tabId.ToString()
            select tabElement).SingleOrDefault();
Run Code Online (Sandbox Code Playgroud)

或者,您可以编写一个扩展方法XElement:

public static string AttributeValueOrDefault(this XElement element,
                                             string attributeName)
{
    XAttribute attr = element.Attribute(attributeName);
    return attr == null ? null : attr.Value;
}
Run Code Online (Sandbox Code Playgroud)

然后使用:

var page = (from element in extensionsDoc.Descendants("page")
            where element.AttributeValueOrDefault("id") == tabId.ToString()
            select element).SingleOrDefault();
Run Code Online (Sandbox Code Playgroud)

或者使用点符号:

var page = extensionsDoc.Descendants("page")
             .Where(x => x.AttributeValueOrDefault("id") == tabId.ToString())
             .SingleOrDefault();
Run Code Online (Sandbox Code Playgroud)

(tabId.ToString()事先调用一次,顺便说一句,而不是每次迭代都是有意义的.)


Igo*_*aka 10

在.NET 4中,LINQ to XML提供了一种方法,它通过使用显式转换来实现:

var page = (
  from tabElement in extensionsDoc.Descendants("page")
    where (string)tabElement.Attribute("id") == tabId.ToString()
    select tabElement
).SingleOrDefault();
Run Code Online (Sandbox Code Playgroud)

如果该属性不存在,则结果将为null.

除了显式string运算符之外,还有大多数基本类型及其Nullable版本.这意味着您可以AttributeOrDefault使用这种语法:

//<element theAttr="12" />
int theAttr = (int?)doc.Element("element").Attribute("missingAttr") ?? 0;
Run Code Online (Sandbox Code Playgroud)

  • 如果没有Element""element"`,那么你的最后一个例子可能会出现NullReferenceException. (2认同)