Working smarter with XElement

Sometimes we developers do things the hard way for no better reason that not knowing that a better way is there.

Here's an example, posted with permission of the author:

[csharp]
XAttribute idAttribute = element.Attribute(XName.Get("id"));
XAttribute typeAttribute = element.Attribute(XName.Get("type"));
XAttribute isSystemCalculatedAttribute = element.Attribute(XName.Get("isSystemCalculated"));
XElement descriptionElement = element.Element(XName.Get("description"));

string name = string.Empty;
string type = string.Empty;
string description = string.Empty;
bool isSystemCalculated = false;

if (idAttribute != null)
{
name = idAttribute.Value;
}

if (typeAttribute != null)
{
type = typeAttribute.Value;
}

if (isSystemCalculatedAttribute != null)
{
bool.TryParse(isSystemCalculatedAttribute.Value, out isSystemCalculated);
}

if (descriptionElement != null)
{
description = descriptionElement.Value;
}

imputationMethodEntity.PutImputationInfo(name, type, isSystemCalculated, description);
[/csharp]

This code works - it's doing nothing more than setting up an object based on information available in an XElement.

Problem is, the code works too hard. What the author didn't know at the time is this: There are predefined explicit casts on XAttribute that take care of the null checks for you.

For example, instead of

[csharp]
string name = string.Empty;
XAttribute idAttribute = element.Attribute(XName.Get("id"));
if (idAttribute != null)
{
name = idAttribute.Value;
}
[/csharp]

You may instead write this:

[csharp]
string name = (string) element.Attribute("id");
[/csharp]

Using Reflector, we can look at the implementation of the string conversion and see how it works:

[csharp]
public static explicit operator string(XAttribute attribute)
{
if (attribute == null)
{
return null;
}
return attribute.value;
}
[/csharp]

This means that our original large block of code can be economically rewritten like this:

[csharp]
var name = (string) element.Attribute("id");
var type = (string)element.Attribute("type");
var description = (string)element.Element("description");
var isSystemCalculated = (bool) element.Attribute("isSystemCalculated");
imputationMethodEntity.PutImputationInfo(name, type, isSystemCalculated, description);
[/csharp]

This pattern repeats itself throughout the .NET framework - features are waiting to be discovered, features that can save you a lot of work, if you could only find them.

I guess that's the point - the discoverability of this kind of thing is poor.

But once you know, you'll never look back.

Blog Tags: 

Comments

What happens for nulls in this case?

var isSystemCalculated = (bool) element.Attribute("isSystemCalculated");

Does it default to false?

In this case:

var isSystemCalculated = (bool) element.Attribute("isSystemCalculated");

You'll get a null returned from Attribute() if the element isSystemCalculated is not present, and the null will trigger an exception.

Alternatively, if you use a nullable bool:

var isSystemCalculated = (bool?) element.Attribute("isSystemCalculated");

then the null will be handled just fine.

If you wanted to default to false, you could use the ?? operator to convert the null:

var isSystemCalculated = ((bool?) element.Attribute("isSystemCalculated")) ?? false;

There are a whole heap of similar casts implemented within the System.Xml namespace - grab a copy of Reflector and have a look.

Thanks Tony. Yes, they are fully documented on MSDN - if you know to look.

The original code quoted at the top of my post was written by a great developer who simply didn't know about the faster way. The .NET framework is now so large that it's futile to expect anyone to know it all - you could spend all your time reading MSDN updates and never write any code.