Conclusion of hidden type with generics?

Possible duplicate:
No type inference with universal extension method

I have a common interface and two specific implementations of it.

Then I have a method, which is an extension method in a collection of objects that implement this interface, which should process the collection and return the processed collection.

The processing operation does not modify objects or create new ones, so I want the output of this method to be of the same type as the input.

In other words, I do not want the output of this method to be a set of interface type, but rather the specific concrete type that I passed into.

However, this leads to a type inference problem when the method is called.

I will illustrate the 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 errors, you should comment and provoke two messages in the corresponding lines:

error 1:
'Interval <int> []' does not contain a definition for "Process" and no extension method "Process" can be found that takes the first argument of type "Interval <int> []" (press F4 to add a usage directive or assembly)

error 2:
Type arguments for the method 'Extensions.Process <TInterval, T> (System.Collections.Generic.IEnumerable <TInterval>)' cannot be taken out of use. Try explicitly specifying type arguments.

The reason, or, I believe, is that the compiler does not look “deep enough” when analyzing whether the extension method is suitable.

If you change the extension method to:

 public static IEnumerable<IInterval<T>> Process<T>( this IEnumerable<IInterval<T>> intervals) { return intervals; } 

Then it compiles, but the output is:

 IEnumerable<IInterval<T>> result = ... 

and not:

 IEnumerable<Interval<int>> result = ... 

Of course, if I specify the types when called, for example:

 var ordered = intervals.Process<IInterval<int>, int>(); 

... then it works, but that’s not all that’s better (IMO.) Is there a way to trick the compiler into type inference for me?

Basically, I want:

  • Get the type that I called the method, outside of it, instead of entering the results into the interface
  • Avoid continuing to tell the compiler that yes, this is really a different call using these types. The reason for this is that this method will be part of a LINQ-like chain of calls, so either I have to return to a known type after each call, or specify the full types for each call.
+7
source share

All Articles