Why does this code work?
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!
No new comments are allowed on this post.
Comments
No comments yet. Be the first!