18

Why must I provide explicitly generic parameter types While the compiler should infer the type?

public static T2 Cast<T1,T2>(this T1 arg) where T2 : class where T1 : class { return arg as T2; } 

Sample Usage:

 objOfTypeT2 = objOfTypeT1.Cast<TypeT1,TypeT2>(); 


Compared to my desired usage with a more intelligent compiler:

 objOfTypeT2 = objOfTypeT1.Cast<TypeT2>(); 

or maybe I should be more intelligent :-)

Beware that I provide the return type. I want to not provide the object that I called the function on it, the method is an Extension Method.

3
  • What's wrong with casting the normal way(s)? Commented Dec 18, 2010 at 10:31
  • 1
    Why not just making a public static T Cast<T>(this object value) { return value as T;}? Commented Dec 18, 2010 at 11:48
  • @Rauhotz I had what you mentioned, Just curiosity and looking for another overload enable me use it with value types, cause I can't make an overload with generic constraints. Commented Dec 18, 2010 at 11:57

3 Answers 3

19

Inference doesn't consider the return type; you can, however, try splitting the generics; for example, you could write code to allow:

.Cast().To<Type2>() 

by having (untested; indicative only)

public static CastHelper<T> Cast<T>(this T obj) { return new CastHelper<T>(obj); } public struct CastHelper<TFrom> { private readonly TFrom obj; public CastHelper(TFrom obj) { this.obj = obj;} public TTo To<TTo>() { // your code here } } 
Sign up to request clarification or add additional context in comments.

2 Comments

@Jani and look at the example - I don't include the from-type; just the destination-type.
Yeah, I'd say that is the only workaround at the moment.
15

The specification limits type parameter inference for generic methods to all or nothing. You can't have partial inference.

The rationale is probably simplifying type inference rules (that are already pretty complex, as they have to take into account overloading rules too).

3 Comments

I guessed that, so I reorder the parameters so that the inferred type would be the last parameter but no chance.
@Jani: Order doesn't really matter here. Either the compiler can infer all the type arguments for you, in which case you can omit them all, or it can't infer at least one. In the latter case, you'll always have to specify all of them explicitly.
For statics you can get around this by putting the function in a dummy toolset class with generic parameters; then you can give the explicit parameters to the class, while the inferred ones are on the function.
3

I've used Marc Gravell's solution and like it, but I can present another alternative.

Because the generic parameters are inferred from the parameters, another option is to use an out parameter for the result instead of a return value.

This have been possible for a long time, but today's C# allows you to declare the variable inline, which I find to be a usable flow.

public static void Cast<T1, T2>(this T1 arg, out T2 result) where T2 : class where T1 : class { result = arg as T2; } 

You can call this as follows

objOfTypeT1.Cast(out Type2 objOfTypeT2); 

1 Comment

Consider making T2 the return value, but rename result to the C# discard identifier _, e.g. T2 result = objOfType1.Cast(out Type2 _);. Nice and succint!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.