代码之家  ›  专栏  ›  技术社区  ›  Eran Betzalel

如何在不存在空异常的情况下使用linq2Xml?

  •  4
  • Eran Betzalel  · 技术社区  · 16 年前

    我编写了这个简单的linq到xml查询,使用linq语法似乎无法避免null异常。我用错了吗?正确的(简短的)Linq2Xml语法应该是什么?

    linq2Xml查询

    var userData =
        queryUserResponseData.Elements("user")
            .Single(u => u.Element("username").Value == userName);
    

    XML

    <data>
        <user>
            <username>User1</username>
            <userid>123</userid>
        </user>
        <user>
            <username>User2</username>
            <userid>456</userid>
        </user>
        <user>
            <userid>999</userid>
        </user>
    </data>
    
    5 回复  |  直到 16 年前
        1
  •  5
  •   m3kh    16 年前

    XElement和XAttribute具有一些显式转换运算符,用于将其值转换为特定类型。它们非常有用,因为当元素或属性丢失时,返回null。

    var userData = queryUserResponseData.Elements("user").Single(u => (string)u.Element("username") == userName);
    
        2
  •  2
  •   ChrisF    16 年前

    从你对艾哈迈德·马格德回答的评论来看:

    问题实际上是在 u.Element("username").Value Resharper通知我可能存在null异常

    听起来你可能在担心一个潜在的问题,而不是真正的问题。您知道,您的数据将意味着您将始终返回1个结果,但是ReSharper无法访问您的数据,因此它强调了一个事实,即如果没有结果,它将生成空引用异常。

    您可以执行以下三项操作之一:

    1. 忽略警告,什么也不做。

    2. 把Linq包在一个袋子里 try {} catch {}

    只有你才能真正决定你想做什么。

        3
  •  1
  •   Ahmad Mageed    16 年前

    Single 意味着您希望正好有一个结果。当返回更多结果时,Single将抛出异常。你可以用 First Last 最后一个。对于多个项目,您将希望在结果上循环并单独访问每个项目。

    如果不存在匹配结果,则可以使用 SingleOrDefault 退票 null 值或所用类型的默认值。

    queryUserResponseData XElement还是XDocument?如果是XDocument,则需要首先访问XML的根,例如:

    var userData = queryUserResponseData.Root.Elements("user")
                     .Single(u => u.Element("username").Value == userName);
    

    用户3 ,它不存在,Single将引发异常。在这种情况下,应使用SingleOrDefault:

    var userData = queryUserResponseData.Elements("user")
                     .SingleOrDefault(u => u.Element("username").Value == "User3");
    
        4
  •  1
  •   Martin JonáÅ¡    16 年前

    根据您对Ahmad答案的评论,我假设当元素没有节点时,您会得到NullReferenceException。你可以这样修理它-

    var userData =
        doc.Elements("user")
        .Single(u => u.Element("username") != null && u.Element("username").Value == userName);
    

    但如果DTD或XSD需要username节点,或者您确定所有元素都有username节点,那么您可以忽略ReSharper警告。

        5
  •  0
  •   Lee    16 年前
    var userData = queryUserResponseData.Elements("user")
        .Select(u => u.Element("username"))
        .Where(uNode => uNode != null)
        .Single(uName => uName.Value == userName);
    
    推荐文章