简体   繁体   English

此C#代码上的NullReferenceException

[英]NullReferenceException on this C# code

Here is the entire code for my class: 这是我班级的全部代码:

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();
        }
    }
}

Basically what it does is parse the information from the returned xml of this address: 基本上,它所做的是从该地址返回的xml中解析信息:

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

Here's how I'm running this code: 这是我运行此代码的方式:

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();

I'm getting an exception on the entire load subforums block; 我在整个加载子论坛块上遇到了异常; any suggestions? 有什么建议么?

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

It's almost certainly that one of the elements you're expecting is missing. 几乎可以肯定,您期望的要素之一丢失了。

If you run it in the debugger you may find that when it throws the exception, it indicates which actual operation it's on, which would make it much easier. 如果您在调试器中运行它,您可能会发现,当它引发异常时,它指示出它正在进行的是哪个实际操作,这将使其更加容易。

Alternatively, break out the parsing of individual components into separate methods: 或者,将单个组件的解析分解为单独的方法:

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)
{
    ...
}

I've found this can keep the query expressions more manageable. 我发现这可以使查询表达式更易于管理。

One way of avoiding NREs when there's a missing element that you're just trying to get the value of is to use a conversion instead of the Value property, eg 当您只想获取元素的缺失元素时,避免NRE的一种方法是使用转换而不是Value属性,例如

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

That will set ID to null if the id element is missing. 如果id元素丢失,它将ID设置为null Obviously if it's actually a required property, throwing the exception is better, but for optional properties it's really useful. 显然,如果它实际上是必需属性,则抛出异常会更好,但是对于可选属性,它确实很有用。

you should probably check to make sure that subforumsXML != null before using your linq on it. 您可能应该在使用linq之前检查以确保subforumsXML != null。

you could break this operation into a couple of lines.... 您可以将此操作分成几行...。

    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
   }
}

You never check whether an element exists. 您永远不会检查元素是否存在。 For example for the UserWhoPosted every item must have a <lastpost> element, which must have a <user> element, which must have <id> , <name> , <url> and <photo> elements. 例如,对于UserWhoPosted,每个项目必须具有一个<lastpost>元素,该元素必须具有一个<user>元素,该元素必须具有<id><name><url><photo>元素。 If any of those are missing, that Element("whatever") will return null so a .Value will fail. 如果缺少任何这些元素,则该Element(“ whatever”)将返回null,因此.Value将失败。

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

To find the problem, try this extension and then call GetElement rather than Element... 要查找问题,请尝试此扩展,然后调用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;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM