关于这个C#代码的NullReferenceException

时间:2010-10-26 15:11:10

标签: c# .net xml linq-to-xml

以下是我班级的完整代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Xml.Linq;

namespace SharpDIC.Entities
{
    /// <summary>
    /// Represents a forum on the Dream.In.Code website.
    /// </summary>
    public class Forum
    {
        //Forum information is given by this XML call:
        //http://www.dreamincode.net/forums/xml.php?showforum=NUMBER_GOES_HERE

        public string Name { get; set; }
        public string ID { get; set; }
        public string URL { get; set; }
        public List<Subforum> Subforums { get; set; }

        /// <summary>
        /// Load a forum by providing an ID.
        /// </summary>
        /// <param name="id">A forum's individual ID number.</param>
        public Forum(string ID)
        {
            WebClient webClient = new WebClient();
            string htmlSource = webClient.DownloadString(new Uri(String.Format("http://www.dreamincode.net/forums/xml.php?showforum={0}", ID)));
            XDocument xml = XDocument.Parse(htmlSource);

            var forumXML = xml.Element("ipb").Element("forum");

            //Load general profile information.
            this.Name = forumXML.Element("name").Value;
            this.ID = forumXML.Element("id").Value;
            this.URL= forumXML.Element("url").Value;

            //Load subforums.
            var subforumsXML = xml.Element("ipb").Element("forum").Element("subforums");
            this.Subforums = (from forum in subforumsXML.Descendants("forum")
                              select new Subforum()
                              {
                                  ID = forum.Element("id").Value,
                                  Name = forum.Element("name").Value,
                                  URL = forum.Element("url").Value,
                                  Description = forum.Element("description").Value,
                                  Type = forum.Element("type").Value,
                                  TopicCount = forum.Element("topics").Value,
                                  ReplyCount = forum.Element("replies").Value,
                                  LastPost = new LastPost()
                                  {
                                      Date = forum.Element("lastpost").Element("date").Value,
                                      Name = forum.Element("lastpost").Element("name").Value,
                                      ID = forum.Element("lastpost").Element("id").Value,
                                      URL = forum.Element("lastpost").Element("url").Value,
                                      UserWhoPosted = new Friend()
                                      {
                                          ID = forum.Element("lastpost").Element("user").Element("id").Value,
                                          Name = forum.Element("lastpost").Element("user").Element("name").Value,
                                          Url = forum.Element("lastpost").Element("user").Element("url").Value,
                                          Photo = forum.Element("lastpost").Element("user").Element("photo").Value,
                                      }
                                  }
                              }).ToList();
        }
    }
}

它的基本功能是解析此地址返回的xml中的信息:

http://www.dreamincode.net/forums/xml.php?showforum=1

以下是我运行此代码的方式:

SharpDIC.Entities.Forum forum = new SharpDIC.Entities.Forum("1");
Console.WriteLine(forum.Name);
Console.WriteLine(forum.URL);
Console.WriteLine(forum.ID);
Console.WriteLine(forum.Subforums[0].LastPost.UserWhoPosted.Name);

Console.ReadLine();

我在整个加载子论坛块上遇到异常;有什么建议吗?

NullReferenceException was not handled. Object reference not set to an instance of an object.

5 个答案:

答案 0 :(得分:1)

几乎可以肯定的是,你所期待的元素之一缺失了。

如果你在调试器中运行它,你可以 找到它抛出异常的时候,它会指示它在哪个实际操作,这会使它更容易。

或者,将各个组件解析为单独的方法:

this.Subforums = subforumsXML.Descendants("forum")
                             .Select(ParseForum)
                             .ToList();

...

static SubForum ParseForum(XElement forum)
{
    return new Subforum
    {
        ID = forum.Element("id").Value,
        ...
        LastPost = ParseLastPost(forum.Element("lastpost"))
    };
}

static LastPost ParseLastPost(XElement lastPost)
{
    ...
}

我发现这可以使查询表达式更易于管理。

当您尝试获取值的缺失元素时,避免NRE的一种方法是使用转换而不是Value属性,例如

ID = (string) forum.Element("id")

如果缺少null元素,则会将ID设置为id。显然,如果它实际上是 required 属性,抛出异常会更好,但对于可选属性,它确实非常有用。

答案 1 :(得分:0)

在使用你的linq之前,你应该检查以确保subforumsXML!= null。

你可以把这个操作分成两行......

    var subforumsXML = xml.Element("ipb").Element("forum").Element("subforums");

// goes to

if ( forumXML != null )    // breakpoint here
{
   // ml.Element("ipb").Element("forum") == forumXML
   var subforumsXML = forumXML.Element("subforums");
   if ( subforumsXML != null )
   {
   // do stuff here
   }
}

答案 2 :(得分:0)

您永远不会检查元素是否存在。例如,对于UserWhoPosted,每个项目必须具有<lastpost>元素,必须具有<user>元素,必须具有<id>元素,<name><url><photo>元素。如果缺少任何元素,那么Element(“whatever”)将返回null,因此.Value将失败。

答案 3 :(得分:0)

在您的链接中,第一个用户没有照片,这可能是

答案 4 :(得分:0)

要找到问题,请尝试使用此扩展程序,然后调用GetElement而不是Element ...

public static System.Xml.Linq.XElement GetElement(this System.Xml.Linq.XContainer doc, string name)
    {
        var element = doc.Element(name);
        if (element == null)
            throw new ApplicationException("Missing element: " + name);
        return element;
    }