Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you guard for Null Reference exceptions in Linq To Xml?

<?xml version="1.0" encoding="utf-8" ?>
<pages> 
  <page id="56">
    <img id="teaser" src="img/teaser_company.png"></img>
  </page>  
</pages>

I have an xml file that defines additional resources for pages within a cms. What's the best way to guard for Null Reference exceptions when querying this file with LinqToXml?

var page = (from tabElement in extensionsDoc.Descendants("page")
where tabElement.Attribute("id").Value == tabId.ToString()
select tabElement).SingleOrDefault();

This code could potentially trigger a Null Reference exception if a page element doesn't have an attribute called "id". Do I have to use a try catch block or is there a way to handle this? For instance return null for page the page object if there's no attribute called "id" for the page element.

like image 395
kitsune Avatar asked Apr 27 '09 10:04

kitsune


People also ask

How to avoid system null reference exception?

To prevent the NullReferenceException exception, check whether the reference type parameters are null or not before accessing them. In the above example, if(cities == null) checks whether the cities object is null or not. If it is null then display the appropriate message and return from the function.

Is null in Linq C#?

LINQ to SQL does not impose C# null or Visual Basic nothing comparison semantics on SQL. Comparison operators are syntactically translated to their SQL equivalents. The semantics reflect SQL semantics as defined by server or connection settings.

What is NullReferenceException in C#?

The runtime throwing a NullReferenceException always means the same thing: you are trying to use a reference, and the reference is not initialized (or it was once initialized, but is no longer initialized). This means the reference is null , and you cannot access members (such as methods) through a null reference.


1 Answers

EDIT: This was clearly written a long time ago - these days I'd definitely go with the cast as per Igor's answer.

The simplest way would be something like:

var page = (from tabElement in extensionsDoc.Descendants("page")
            let idAttribute = tabElement.Attribute("id")
            where idAttribute != null 
                  && idAttribute.Value == tabId.ToString()
            select tabElement).SingleOrDefault();

Alternatively you could write an extension method to XElement:

public static string AttributeValueOrDefault(this XElement element,
                                             string attributeName)
{
    XAttribute attr = element.Attribute(attributeName);
    return attr == null ? null : attr.Value;
}

then use:

var page = (from element in extensionsDoc.Descendants("page")
            where element.AttributeValueOrDefault("id") == tabId.ToString()
            select element).SingleOrDefault();

Or to use dot notation:

var page = extensionsDoc.Descendants("page")
             .Where(x => x.AttributeValueOrDefault("id") == tabId.ToString())
             .SingleOrDefault();

(It would make sense to call tabId.ToString() once beforehand, btw, rather than for every iteration.)

like image 77
Jon Skeet Avatar answered Oct 03 '22 22:10

Jon Skeet