Neir0
Neir0

Reputation: 13377

Check on null reference

i have the follow code:

searchResults.SearchResultCollection.Add(
                new SearchResult()
                    {
                        Header =
                        HttpUtility.HtmlDecode(
                        htmlDocument.DocumentNode
                        .SelectSingleNode(initialXPath + "h3") 
                        .InnerText),
                        Link = HttpUtility.HtmlDecode(
                        htmlDocument.DocumentNode
                        .SelectSingleNode(initialXPath + "div/cite")
                        .InnerText)
                    }
                );

Sometimes htmlDocument.DocumentNode.SelectSingleNode(....) returns null and my application crashed with NullReferenceException. Ofcourse i can write code which check returned value on null reference but then code will be overly verbose. What is graceful way to do that?

Upvotes: 3

Views: 2242

Answers (4)

Nathan Baulch
Nathan Baulch

Reputation: 20703

Create a Try version of SelectSingleNode as an extension method.

public static class XmlNodeExtensions
{
    public static bool TrySelectSingleNode(this XmlNode node,
                                           string xpath,
                                           out XmlNode result)
    {
        result = node.SelectSingleNode(xpath);
        return (result != null);
    }
}

You would then change your code to:

XmlNode node;
searchResults.SearchResultCollection.Add(
    new SearchResult
    {
        Header = HttpUtility.HtmlDecode(
            htmlDocument.DocumentNode
                .TrySelectSingleNode(initialXPath + "h3", out node)
                    ? node.InnerText
                    : null),
        Link = HttpUtility.HtmlDecode(
            htmlDocument.DocumentNode
                .TrySelectSingleNode(initialXPath + "div/cite", out node)
                    ? node.InnerText
                    : null)
    });

Upvotes: 3

Daniel Brückner
Daniel Brückner

Reputation: 59705

Just write an extension method.

public static class Extensions
{
   public static String SafeInnerText(this XmlElement node, String default)
   {
      return (node != null) ? node.InnerText : default;
   }
}

And then use it as follows.

[...].SelectSingleNode(initialXPath + "h3").SafeInnerText("NoInnerText");

Yes, I know, default is a reserved keyword...

Upvotes: 2

Dean Harding
Dean Harding

Reputation: 72678

You could create an extension method on XmlNode, like so:

public static class ExtensionMethods
{
    public string GetNodeText(this XmlNode node, string xPath)
    {
        var childNode = node.SelectSingleNode(xPath);
        return (childNode == null)
            ? "" : childNode.InnerText;
    }
}

searchResults.SearchResultCollection.Add(
    new SearchResult()
        {
            Header = HttpUtility.HtmlDecode(
                    htmlDocument.DocumentNode.GetNodeText(initialXPath + "h3"),
            Link = HttpUtility.HtmlDecode(
                    htmlDocument.DocumentNode.GetNodeText(initialXPath + "div/cite")
        }
    );

Personally, I'd probably just suck it up and put in the null tests explicityly, though :)

Upvotes: 3

Vivin Paliath
Vivin Paliath

Reputation: 95588

I don't see how checking for null is overly verbose. If you're doing the exact same thing everywhere (pulling a node out). You can abstract that out into a single method/function that performs the null-check. That way you won't have a null-check everywhere you are trying to grab a node since the null-check is neatly encapsulated inside the function/method.

Otherwise, I think you would have to perform an explicit null-check. There may be other ways to do it, but be careful. There is a fine line between elegant, clever, and hackish. ;)

Upvotes: 1

Related Questions