1

For example this snippet of code:

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 warns me of a possible NullReferenceException on the comment.Element lines. True enough, the exception fired.

Any suggestion of how to avoid this? What about if it returns null, just return an empty string, is this possible?

  • Possible duplicate of [What is a NullReferenceException and how do I fix it?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Nasreddine Oct 04 '15 at 09:06

4 Answers4

2

I Prefer to have an extension class for it:

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

and use it as :

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

or

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

Also there are other ways like:

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

Saeed Amiri
  • 22,252
  • 5
  • 45
  • 83
1

I can only think you'd need to check each element reference thus:

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

The last is a little weak as there's two nodes that really should be checked but the nesting would look a little unpleasant but the only way to be sure.

EDIT ----

As an extension method:

public static class MyExtensions
{

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

}

You can then replace .Value with .ValueSafe, that said, not had an opportunity to test.

Lazarus
  • 41,906
  • 4
  • 43
  • 54
  • Better to create some wrapper like extentin for such long row ->comment.Element("id")==null)?"":comment.Element("id").Value – Andrew Orsich Dec 17 '10 at 16:23
  • Your first code is ugly, and Steel you didn't check elements, and in your first sample `Owner = (comment.Element("user")==null)?"":comment.Element("user").Element("name").Value` if `Element("name")` is null, you will get exception. – Saeed Amiri Dec 17 '10 at 16:33
  • @Saeed: Ugly is a matter of opinion (though I'm not disputing here) and really needs to take the OPs ability into account. Not everyone understands extension methods. As for the nested node comparison, I had noted that in my comment regarding the weak checking. – Lazarus Dec 17 '10 at 16:38
  • @Lazarus, as you wroted is "unpleasant" so at least modify your answer, you said just this way ... – Saeed Amiri Dec 17 '10 at 16:44
  • @Saeed: I really don't understand what you mean and why it's so important. – Lazarus Dec 17 '10 at 16:49
  • You wrote `but the only way to be sure` your statement is false in all, I didn't downvoted you because you edited and add extension method approach I can list at least 4 different ways to do this. – Saeed Amiri Dec 17 '10 at 16:52
  • @Saeed: Yes, the only way to be sure is to check **BOTH** nodes. Perhaps there's just a little language problem here. – Lazarus Dec 19 '10 at 11:12
1

A few extensions could help:

Example:

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

Usage:

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();
}
decyclone
  • 30,394
  • 6
  • 63
  • 80
0

It is possible - you would need to wrap each comment.Element().Value statement in a function.

I like to use:

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

As for the last line, you need to be extra carful there to make sure comment.Element("user") is not null and handle that case if it is.

zsalzbank
  • 9,685
  • 1
  • 26
  • 39