【问题标题】:Possible NullReferenceException可能的 NullReferenceException
【发布时间】:2010-12-17 16:16:46
【问题描述】:

例如这个sn-p的代码:

private void LoadComments(Member member, XElement commentsXml)
{
    member.Comments = (from comment in commentsXml.Descendants("comment")
                     select new Comment()
                     {
                         ID = comment.Element("id").Value,
                         Text = comment.Element("text").Value,
                         Date = comment.Element("date").Value,
                         Owner = comment.Element("user").Element("name").Value
                     }).ToList();
}

ReSharper 警告我可能在 comment.Element 行上出现 NullReferenceException。确实,异常被触发了。

关于如何避免这种情况的任何建议?如果它返回null呢,只返回一个空字符串,这可能吗?

【问题讨论】:

标签: c# nullreferenceexception


【解决方案1】:

我更喜欢有一个扩展类:

public static class XElementExtension
{
   public static string GetValue(this XElement input)
   {
      if (input == null)
        return null;
      return input.Value as T;
   }

   public static XElement GetSubElement(this XElement element, string id)
   {
      if (element == null)
        return null;
      return element.Element(id);
   }
}

并将其用作:

ID = comment.Element("id").GetValue()

Owner = comment.Element("user").GetSubElement("name").GetValue()

还有其他方法,比如:

http://www.codeproject.com/KB/cs/maybemonads.aspx

【讨论】:

  • 我什至不知道那些存在,但它们看起来很棒!每天学习新东西。
  • 扩展方法是否解决了 resharper 的“Possible NullReferenceException”警告?
  • @Vincent,我不记得 resharper 中发生了什么,你可以简单地测试一下。
【解决方案2】:

一些扩展可能会有所帮助:

示例:

public static class XElementExtensions
{
    public static XElement GetElement(this XElement element, XName elementName)
    {
        if (element != null)
        {
            XElement child = element.Element(elementName);

            if (child != null)
            {
                return child;
            }
        }

        return null;
    }

    public static String GetElementValue(this XElement element, XName elementName)
    {
        if (element != null)
        {
            XElement child = element.Element(elementName);

            if (child != null)
            {
                return child.Value;
            }
        }

        return null;
    }
}

用法:

private void LoadComments(Member member, XElement commentsXml)
{
    member.Comments = (from comment in commentsXml.Descendants("comment")
                        select new Comment()
                        {
                            ID = comment.GetElementValue("id"),
                            Text = comment.GetElementValue("text"),
                            Date = comment.GetElementValue("date"),
                            Owner = comment.GetElement("user").GetElementValue("name")
                        }).ToList();
}

【讨论】:

    【解决方案3】:

    我只能认为您需要检查每个元素引用:

    private void LoadComments(Member member, XElement commentsXml)
    {
        member.Comments = (from comment in commentsXml.Descendants("comment")
                         select new Comment()
                         {
                             ID = (comment.Element("id")==null)?"":comment.Element("id").Value,
                             Text = (comment.Element("text")==null)?"":comment.Element("text").Value,
                             Date = (comment.Element("date")==null)?"":comment.Element("date").Value,
                             Owner = (comment.Element("user")==null)?"":comment.Element("user").Element("name").Value
                         }).ToList();
    }
    

    最后一个有点弱,因为确实应该检查两个节点,但嵌套看起来有点不愉快,但这是唯一确定的方法。

    编辑----

    作为扩展方法:

    public static class MyExtensions
    {
    
        public static string ValueSafe(this XElement target)
        {
            if (target==null)
                { return ""; }
            else
                { return target.Value; }
        }
    
    }
    

    然后您可以将.Value 替换为.ValueSafe,也就是说,没有机会测试。

    【讨论】:

    • 最好为这么长的行创建一些像extentin这样的包装器->comment.Element("id")==null)?"":comment.Element("id").Value
    • 您的第一个代码很丑陋,而 Steel 您没有检查元素,并且在您的第一个示例 Owner = (comment.Element("user")==null)?"":comment.Element("user").Element("name").Value 如果Element("name") 为空,您将得到异常。
    • @Saeed:丑陋是见仁见智的问题(尽管我在这里没有争议),确实需要考虑到 OP 的能力。不是每个人都了解扩展方法。至于嵌套节点比较,我在关于弱检查的评论中注意到了这一点。
    • @Lazarus,正如你所写的那样“令人不快”,所以至少修改你的答案,你就是这样说的......
    • @Saeed:我真的不明白你的意思以及为什么它如此重要。
    【解决方案4】:

    这是可能的 - 您需要将每个 comment.Element().Value 语句包装在一个函数中。

    我喜欢用:

    public string UnNull(object v)
    {
       if (v == null) return "";
       return v.ToString();
    }
    

    至于最后一行,您需要格外小心,以确保 comment.Element("user") 不是 null 并处理这种情况。

    【讨论】:

    • 您可能会在尝试获取不存在的元素值时遇到异常,因为字符串为空。
    猜你喜欢
    • 2011-01-23
    • 2012-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多