Why does this code work?

25 April 2010 · 2 minute read · .net · c# · operator-overload

In the discussion on the Umbraco forum about using LINQ to Umbraco I posted a short code snippet of something we write fairly frequently at TheFARM using our version of LINQ with Umbraco.

I thought I’d post the challenge to my trusty followers, for them to see if they know why the code works. First off the code:

IEnumerable<XElement> nodes = UmbXmlLinqExtensions.GetNodeByXpath(...); 
IEnumerable<IUmbracoPage> pages = nodes.Select(n =>(IUmbracoPage)(UmbracoPage)n);

What the XPath being evaluated isn’t important, what is important is you’ll notice that we have a collection of System.Xml.Linq.XElement’s, but then it’s directly casting each XElement to IUmbracoPage.

Here’s the skeleton for the class and interface:

public interface IUmbracoPage { ... } 
public class UmbracoPage : IUmbracoPage { ... }

Again the body of the interface isn’t important, what is important is that the class only inherits from the interface, it does not inherit from XElement.

###Why does this work###

Well the answer is actually very simple, and it’s a really handy feature of the C# language, explicit operators.

Explicit operators allow you to define explicit casting between types. So the code that was missing from my original post was this:

public static explicit operator UmbracoPage(XElement x) {
    return new UmbracoPage(x);
}

What I’ve done here is defined how the compiler is to treat a casting of an XElement to an instance of UmbracoPage, and since UmbracoPage inherits IUmbracoPage there is already a defined casting to it.

Inside the body of my explicit operator I can do anything I desire, here I’m just returning a new instance, passing the XElement to the constructor.

I find it really quite elegant, and that it reduces code smell quite nicely.

But explicit operators also have a buddy, in the form of implicit operators (which was the close-but-no-cigar answer). These work by the type being defined by the assignment target, eg:

UmbracoPage page = xElement;

I’m personally not a fan of implicit operators though, I find them less obvious when you’re reading code.

So there you have it, a slightly obscure language feature to play with!


Published: 2017-07-30 20:47:37 +1000 +1000, Version: bfd8bbd