Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 6,125 | Comments: 45,490

filter by tags archive

Generic extension methods

time to read 7 min | 1294 words

I was playing around with the compiler when I hit this interesting feature. I was very surprised to see that this has compiled successfully.

   1: static class Program
   2: {
   3:     static void Main(string[] args)
   4:     {
   5:         IProcesser<GZipStream> p = null;
   6:         p.HasTimeout();
   7:     }
   8: }
  10: public static class Extensions
  11: {
  12:     public static bool HasTimeout<T>(this IProcesser<T> s)
  13:         where T : Stream
  14:     {
  15:         return s.Desitnation.CanTimeout;
  16:     }
  17: }
  19: public interface IProcesser<TDestination>
  20:     where TDestination : Stream
  21: {
  22:     TDestination Desitnation { get; }
  23: }



Maybe I'm missing something but any reason it shouldn't?

Because it's a nulled variable?

You can do the same with any method on a variable:

    static void Main(string[] args)


        string p = null;

        string[] q = p.Split(',');


Sure it'd fail during execution, but not on compile.

We figured this out a while back, and do a test for a null reference that throws an exception, if it's a critical part of the app.

Ayende Rahien


The extension method is a generic method.

I was surprised that that worked.


Actually, I did look at the top afterwards, at the name of the post - and yeah... red faced now :)

Yep, we have a couple of generic methods as extension methods too - comes nice and handy when you need to do the same thing in a few different cases.

We're starting to build up some core extension methods to be shared between specific projects, and each project has it's own extension method library - but we do like having some generics used on the global ones that can work between a couple of project idiosyncrasies.

Apologies to the assume, it did make an ass out of me, at least :)

Craig Shearer

There are two things about this that puzzle me - firstly and superficially, there is a spelling mistake - Desitnation instead of Destination - but it doesn't matter to the compiler.

But, there's no implementation of the getter (TDestination Desitnation {get;}) That is weird!

Oh, and if you're going to show us code, it would be nice if it didn't have line numbers - it makes it terrible to cut and paste.

Ayende Rahien

I am trying to find my previous code highlighter.

As for why it compiles, that is an interface, not a class

VIjay Santhanam

It seems like one must check for a not null "this" argument as a precondition in extension methods.

Also, the compiler is smarter with generic methods. Notice you don't have to specify the parameters to any generic System.Linq ext methods.

Two typical linq extension methods include

public static IQueryable AsQueryable(this IEnumerable source);

public static IQueryable AsQueryable(this IEnumerable source);

If u have the code

string[] items = {"a","b"."c" ,"two"};


the second line will use the generic method and not the first signature.

Is this a case of the compiler inferring type when picking call methods?

Thomas Krause

Why are you surprised?

Isn't the whole LINQ stuff based on extension methods for the (generic) IEnumerable interface?


Well, maybe I am missing the obvious, but I don't see anything strange. It's a static method behind the scenes, so the compiler shouldn't care whether you are passing a null argument to it. I don't see why being a generic method should change that fact.

Ayende Rahien

VIjay ,

Yes, it does.

It is significantly smarter than it was for 2.0

Julian Birch

Actually, the thing I find most surprising is that the type inference works. I'm pretty sure the pretty similar code you could write for .NET 2.0 doesn't compile.

The whole "extension methods aren't instance methods" is a bit weird, although I have to admit I've already abused it. (i.e. made it not throw an exception)

Ayende Rahien


Methods for generic interface, yes.

Generic methods, I wouldn't have expected that.

Ayende Rahien


I am surrised that the compiler can pick it up, actually.

Jimmy Bogard

Awww old news


It's very interesting indeed. I've been playing around with specification-type extensions, for things like IComparable.

It was very surprising the first time I compiled it. We had a little bet at the office whether it would or not. And an interesting DBC-style implementation too:


You do still run into the problems of generic constraints, and you have to weigh whether you target the constraint directly or use constraints.

Jon Skeet


Even talking about generic methods, LINQ is still stuffed full of examples.

Take Select - yes, it acts on a particular generic interface, but it has to project to another generic interface (a sequence of the result type) and that result type is specified by a type parameter.

Indeed, even simple methods like Where which only act on a generic interface are still generic methods - it's not like the type itself is Enumerable with extension methods for the corresponding IEnumerable. There are relatively few methods in LINQ which aren't generic methods.


Jimmy Bogard

Also, not only does it compile successfully, but your generic constraints are correctly interpreted by Intellisense. It's not all IProcessor implementations that catch it, it's only those that conform to the constraint.

Even removing the constraint on the interface, the Intellisense still pops up correctly if you constrain the generic method. I haven't tried R# code completion yet, this is only VS built-in intellisense.

Luke Breuer

Ayende, I've been using the following code (which will be mangled by the blog comment engine, grrrr) for a while:

public static string Join(this IEnumerable strings, string delimiter)


return strings.Any()

    ? string.Join(delimiter, strings as string[] ?? strings.ToArray())

    : "";


I also echo Thomas Krause: LINQ is built on IEnumerable and extension methods working with it, among other things.



Maybe this is by design (callvirt vs. call). This blog post explains it: http://blogs.msdn.com/howard_dierking/archive/2007/02/09/more-c-3-0-extension-methods.aspx

Here's another one:



I'm really surprised that you had not come across this already. I've been doing this since early CTP releases. Generic extension methods are fundamental to C# 3.0 programming.

Glad you found it. Now I'm sure you'll come up with lots of interesting uses for this feature.

Comment preview

Comments have been closed on this topic.


  1. RavenDB 3.5 Whirlwind tour: I need to be free to explore my data - one day from now
  2. RavenDB 3.5 whirl wind tour: I'll have the 3+1 goodies to go, please - 4 days from now
  3. The design of RavenDB 4.0: Voron has a one track mind - 5 days from now
  4. RavenDB 3.5 whirl wind tour: Digging deep into the internals - 6 days from now
  5. The design of RavenDB 4.0: Separation of indexes and documents - 7 days from now

And 11 more posts are pending...

There are posts all the way to May 30, 2016


  1. The design of RavenDB 4.0 (14):
    05 May 2016 - Physically segregating collections
  2. RavenDB 3.5 whirl wind tour (14):
    04 May 2016 - I’ll find who is taking my I/O bandwidth and they SHALL pay
  3. Tasks for the new comer (2):
    15 Apr 2016 - Quartz.NET with RavenDB
  4. Code through the looking glass (5):
    18 Mar 2016 - And a linear search to rule them
  5. Find the bug (8):
    29 Feb 2016 - When you can't rely on your own identity
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats