Omer van Kloeten's .NET Zen

Programming is life, the rest is mere details

News

Omer van Kloeten's Facebook profile

Get Firefox

.NET Resources

Articles :: CodeDom

Articles :: nGineer

Culture

Projects

Generic Parameter Inference

public static void Do<T>(this TBase value) where T : BaseClass<TBase>

The above line of code does not compile. I've been mulling over this for about half an hour and have not come up with a single logical reason why it shouldn't, strong-typing wise, except that it doesn't.

I can understand why using Type Inference (calling the method without the generic parameter), you could never bind to one predetermined T - after all, there may be an infinite amount of types that derive from BaseClass<TBase> and that's just when using TBase's topmost level of inheritance.

However, using a call to Do with the T generic parameter explicitly stated, there can be only one option for TBase, since:

  1. It is a class and you can never derive twice from the same type in your line of inheritance, so there's no fearing that T would derive from both BaseClass<A> and BaseClass<B> somewhere along that line.
  2. It is not an interface, where you could implement both ISomething<A> and ISomething<B>

Does anyone have any ideas?

Comments

Max said:

Well, clearly the problem is that the hypothetical type parameter TBase is not in the list of bound type parameters (between the <>). This would work (I think):

public static void Do<T, TBase>(this TBase value) where T : BaseClass<TBase>

But then of course C# would not be clever enough to infer T or TBase for you. This is just one of the limitations in C#s generics support which has bitten me in the past: many type safe programs are excluded :(

In some ways Java generics, despite their reputation, are actually more powerful (e.g. consider that you can keep around an ArrayList<Whatever<?>>), but even Javas use site variance won't help you with this issue as far as I can see. Sorry!

Your only option is to do what I did and switch to using Haskell ;-)

# October 29, 2007 12:34 PM

Stuart Ballard said:

Well, for starters, you're using TBase without declaring it. It's like saying that i = 1 ought to compile without an "int i" anywhere.

Try this:

public static void Do<T,TBase>(this TBase value) where T : BaseClass<TBase>

# October 29, 2007 12:49 PM

Omer van Kloeten said:

Max, Stuart - Maybe I wasn't clear enough in my post. I'm talking about a non-existent feature in C#, where I wouldn't have to state TBase as a generic parameter, but that instead, one would be inferred for me. I was just looking for a reason for why this was never implemented. Maybe there's a logical pitfall here somewhere...

If there are none, I think this may be a strong candidate for a C# vNext feature.

# October 29, 2007 1:09 PM

Joe Chung said:

Internally, BaseClass<TBase> needs to get mapped to an anonymous type after the TBase type is specified.

If you don't specify what TBase is, like you're suggesting, the compiler doesn't have enough information to know if you intend TBase to be a generic parameter or a class.

Type inference is not magic.

# October 29, 2007 1:14 PM

Omer van Kloeten said:

Thanks, Joe - this is exactly the problem I was looking for :)

# October 29, 2007 1:21 PM

dln said:

What is solve the proplem? Answere is...?

# February 5, 2008 2:56 AM

Omer van Kloeten said:

The compiler assumes TBase is a type that it doesn't know so it stops with an error.

# February 5, 2008 11:05 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)