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?

1

4 Answers 4

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

Sign up to request clarification or add additional context in comments.

3 Comments

I didn't know those even existed, but they seem great! Learn something new every day.
Does the extension method solve the "Possible NullReferenceException" warning from resharper?
@Vincent, I cannot remember what happens in resharper, you can simply test it.
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();
}

Comments

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.

7 Comments

Better to create some wrapper like extentin for such long row ->comment.Element("id")==null)?"":comment.Element("id").Value
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: 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, as you wroted is "unpleasant" so at least modify your answer, you said just this way ...
@Saeed: I really don't understand what you mean and why it's so important.
|
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.

1 Comment

You may then get exceptions trying to get element values that don't exist because the string is empty.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.