Lennart
Lennart

Reputation: 10343

Unable to call extension method with null-object

I'm trying to parse XML attributes out of a XmlDocument. Since it's possible, that a certain node does not have a specific attribute, I've created an extension method to check the attribute and return a default value if the attribute is null or invalid:

public static bool TryParseOrDefault(this string toParse, bool defaultValue)
 {
   if(toParse == null) return defaultValue;
   bool result;
   if(Boolean.TryParse(toParse, out result))
   {
        return result;
   }
   return defaultValue;
 }

This works well enough, however it does not when the object I want to check is null:

var whatever = column.Attributes["SomeAttribute"].Value.TryParseOrDefault(true);

In this case the column node doesn't have the SomeAttribute attribute, thus Value is null and a NullReferenceException is thrown. Why is that? I thought extension methods are supposed to work on null objects, since the call basically translates to this:

MyExtensions.TryParseOrDefault(column.Attributes["SomeAttribute"].Value,true);

Upvotes: 2

Views: 210

Answers (2)

Rune FS
Rune FS

Reputation: 21752

It's not the .Value that's null but the attribute ans you are therefore effectively doing this null.Value which throws the mentioned exception. You could change the extension method to accept a XAttribute instead of a string

public static bool TryParseOrDefault(this XAttribute toParse, bool defaultValue)
 {
   if(toParse == null) return defaultValue;
   bool result;
   if(Boolean.TryParse(toParse.Value, out result))
   {
        return result;
   }
   return defaultValue;
 }

and then call it like this

var whatever = column.Attributes["SomeAttribute"].TryParseOrDefault(true);

you could also create an override to the LINQ2XML extension method

public static bool Attribute(this XElement elem, string attributeName, bool defaultValue)
 {
   var toParse = (string)elem.Attribute(attributeName);
   bool result;
   if(Boolean.TryParse(toParse, out result))
   {
        return result;
   }
   return defaultValue;
 }

which you'd then use like this:

var whatever = column.Attribute("SomeAttribute",true);

Upvotes: 4

Jon Skeet
Jon Skeet

Reputation: 1503140

I suspect the problem is that if Attributes["SomeAttribute"] return null - so finding the Value property will fail. If column is an XmlElement, that would certainly be the case - look at the XmlAttributeCollection.ItemOf(string) property (the indexer):

Property value
The XmlAttribute with the specified name. If the attribute does not exist, this property returns null.

You're right about the translation of the extension method - but I don't think that's the problem. It's easy to test that though - just split the statement up for diagnostic purposes:

string tmp = column.Attributes["SomeAttribute"].Value;
var whatever = tmp.TryParseOrDefault(true);

I suspect you'll find the exception is on the first line, not the second.

You may wish to consider using LINQ to XML, which makes this easier - there you could use:

string tmp = (string) column.Attribute("SomeAttribute");

and that will return null if the attribute is missing, because the explicit conversion from XAttribute to string will return null if the "source" of the conversion is a null reference.

(If you only need this for XmlAttribute, then Rune's answer is a great one too. It depends on what you're trying to do.)

Upvotes: 3

Related Questions