13.07.2015 Views

C# in Depth

C# in Depth

C# in Depth

SHOW MORE
SHOW LESS
  • No tags were found...

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Extension method syntax26110.2.3 How extension methods are foundIt’s important to know how to call extension methods—but it’s also important to knowhow to not call them—how to not be presented with unwanted options. To achievethat, we need to know how the compiler decides which extension methods to use <strong>in</strong>the first place.Extension methods are made available to the code <strong>in</strong> the same way that classes aremade available without qualification—with us<strong>in</strong>g directives. When the compiler seesan expression that looks like it’s try<strong>in</strong>g to use an <strong>in</strong>stance method but none of the<strong>in</strong>stance methods are compatible with the method call (if there’s no method with thatname, for <strong>in</strong>stance, or no overload matches the arguments given), it then looks for anappropriate extension method. It considers all the extension methods <strong>in</strong> all theimported namespaces and the current namespaces, and matches ones where there’san implicit conversion from the expression type to the extended type.NOTE Implementation: How does the compiler spot an extension method <strong>in</strong> a library? Towork out whether or not to use an extension method, the compiler has tobe able to tell the difference between an extension method and othermethods with<strong>in</strong> a static class that happen to have an appropriate signature.It does this by check<strong>in</strong>g whether System.Runtime.CompilerServices.ExtensionAttribute has been applied to the method. This attribute is newto .NET 3.5, but the compiler doesn’t check which assembly the attributecomes from. This means that you can still use extension methods even ifyour project targets .NET 2.0—you just need to def<strong>in</strong>e your own attributewith the right name, <strong>in</strong> the right namespace.If multiple applicable extension methods are available for different extended types(us<strong>in</strong>g implicit conversions), the most appropriate one is chosen with the “better conversion”rules used <strong>in</strong> overload<strong>in</strong>g. For <strong>in</strong>stance, if IChild <strong>in</strong>herits from IParent, andthere’s an extension method with the same name for both, then the IChild extensionmethod is used <strong>in</strong> preference to the one on IParent. This is crucial to LINQ, as you’llsee <strong>in</strong> section 12.2, where we meet the IQueryable <strong>in</strong>terface.It’s important to note that <strong>in</strong>stance methods are always used beforeextension methods, but the compiler doesn’t warn of an extensionmethod that matches an exist<strong>in</strong>g <strong>in</strong>stance method. If a new version of theframework were to <strong>in</strong>troduce a CopyTo method <strong>in</strong> Stream that took thesame parameters as our extension method, recompil<strong>in</strong>g our code aga<strong>in</strong>stthe new framework would silently change the mean<strong>in</strong>g of the methodcall. (Indeed, that’s one reason for choos<strong>in</strong>g CopyTo <strong>in</strong>stead ofWriteTo—we wouldn’t want the mean<strong>in</strong>g to change depend<strong>in</strong>g onwhether the compile-time type was Stream or MemoryStream.)One potential problem with the way that extension methods are made available tocode is that it’s very wide-rang<strong>in</strong>g. If there are two classes <strong>in</strong> the same namespace conta<strong>in</strong><strong>in</strong>gmethods with the same extended type, there’s no way of only us<strong>in</strong>g the extensionmethods from one of the classes. Likewise, there’s no way of import<strong>in</strong>g aWarn<strong>in</strong>g:subtleversion<strong>in</strong>gissue!Licensed to Rhona Hadida

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!