tags:

views:

130

answers:

2

I have the following method:

public TResult Get<TGenericType, TResult>() 
                          where TGenericType : SomeGenericType<TResult>
                          where TResult : IConvertible {
   //...code that uses TGenericType...
   //...code that sets someValue...
   return (TResult) someValue;
}

Right now, a user of this method has to use it like this:

//notice the duplicate int type specification
int number = Get<SomeGenericType<int>, int>();

Why do I have to specify TResult in the method defintion? The compiler already knows TResult since I specified it in TGenericType. Ideally (if the C# compiler was a little smarter), my method would look like this:

public TResult Get<TGenericType>() 
                          where TGenericType : SomeGenericType<TResult>
                          where TResult : IConvertible {
   //...code that uses TGenericType...
   //...code that sets someValue...
   return (TResult) someValue;
}

So the user could just simply use it like this:

//much cleaner
int number = Get<SomeGenericType<int>>();

Is there any way to do what I want to do?

+5  A: 

C# specification does not allow inferring half of type arguments. You should either let the compiler to infer all the type arguments (which is not always applicable, like in your case) or manually specify all of them.

UPDATE (reply to comment): While I'm not on the C# team to give an absolute answer to your question, my speculation is that the complexity of overload resolution (which is already mind-blowing; you know that if you read that section of C# spec) would increase significantly if they wanted to allow half of types to be inferred and half not (especially considering the fact that you can overload methods solely by the number of generic arguments).

Mehrdad Afshari
But why did they specify that in the C# specification? It's not like there is anything unsafe about it.
Hermann
Look into some of the C++ rules, including partial specialization of templates and how access specifiers work. Usually things work smoothly, but there are gotchas lurking here and there. Since one of the ideas behind Java and C# was to avoid C++'s complication, accepting a little inconvenience instead, this is right in line.
David Thornley
+1  A: 

It depends...

If you're just using SomeGenericType<TResult>, you can do:

public TResult Get<TResult>() where TResult : IConvertible {
    SomeGenericType<TResult> myInstance = ...
    //...code that sets someValue...
    return (TResult) someValue;
}

There isn't necessarily a way to put the first type in there, in this case. Since your example isn't passing in a SomeGenericType<TResult> explicitly as a parameter, it suggests this would be possible.

Otherwise, you need to completely specify all of your generic arguments. Unfortunately, that's just the way it is in C#.

Reed Copsey
Sure, but I do need to use SomeGenericType<TResult> in the method. I'll update my sample code to make that clear.
Hermann
Yeah, but look at my code - as long as it's not passed in as a parameter to the method, you can use SomeGenericType<TResult> in the method (ie: if you construct one in the method). Since you know TResult, this works fine. As I said - it can work in some cases...
Reed Copsey
Sorry, I meant I need to use TGenericType (see my updated sample code).
Hermann