Possible Duplicate:
No type inference with generic extension method
I have a generic interface, and two concrete implementations of it.
I then have a method which is an extension method on a collection of objects implementing that interface, which is supposed to process the collection and return the processed collection.
The processing operation does not change the objects nor produce new ones, so I want the output from that method to be the same type as the input.
In other words, I don't want the output from the method to be a collection of the interface type, rather the actual concrete type I passed in.
However, this leads to a problem with type inference when calling the method.
I'll illustrate with a LINQPad example:
void Main()
{
var intervals = new Interval<int>[]
{
new Interval<int>(),
new Interval<int>(),
};
var ordered1 = intervals.Process(); // error 1
// var ordered2 = Extensions.Process(intervals); // error 2
}
public static class Extensions
{
public static IEnumerable<TInterval> Process<TInterval, T>(
this IEnumerable<TInterval> intervals)
where TInterval : IInterval<T>
{
return intervals;
}
}
public interface IInterval<T> { }
public class Interval<T> : IInterval<T> { }
This gives me the following two compile-time error, you have to comment out and in the relevant lines to provoke the two messages:
error 1:
'Interval<int>[]' does not contain a definition for 'Process' and no extension method 'Process' accepting a first argument of type 'Interval<int>[]' could be found (press F4 to add a using directive or assembly reference)error 2:
The type arguments for method 'Extensions.Process<TInterval,T>(System.Collections.Generic.IEnumerable<TInterval>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
The reasons, or so I assume, is that the compiler is not looking "deeply enough" when analyzing whether the extension method will fit.
If I change the extension method to:
public static IEnumerable<IInterval<T>> Process<T>(
this IEnumerable<IInterval<T>> intervals)
{
return intervals;
}
Then it compiles, but thus the output is:
IEnumerable<IInterval<T>> result = ...
and not:
IEnumerable<Interval<int>> result = ...
Of course, if I specify the types when calling, like this:
var ordered = intervals.Process<IInterval<int>, int>();
... then it works, but that's not really all that better (IMO.) Are there any way to trick the compiler into inferring the type for me?
Basically, I want to:
- Get the type I called the method with out of it, instead of the results being typed to the interface
- Avoid having to keep telling the compiler that yes, this is indeed another call using these types. The reason for this is that the method will be part of LINQ-like call chain, so either I have to cast back to the known type after each call, or specify the full types for each call.