delete
delete

Reputation:

Possible NullReferenceException

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?

Upvotes: 1

Views: 1085

Answers (4)

Saeed Amiri
Saeed Amiri

Reputation: 22565

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

Upvotes: 2

Lazarus
Lazarus

Reputation: 43094

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.

Upvotes: 1

decyclone
decyclone

Reputation: 30840

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

Upvotes: 1

zsalzbank
zsalzbank

Reputation: 9857

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.

Upvotes: 0

Related Questions