John
John

Reputation: 961

Returning different type via generics in C#

My generic extension method signature:

public static class MyExtensions
{
    public static IEnumerable<R> DoThing<T, R>(this IEnumerable<T> source)
        where T : class
        where R : class
    {
        throw new NotImplementedException();
    }
}

My usage pattern:

List<MyItem> codes = new List<MyItem>();
List<MyNewItem> newValues = codes.Where(o => o.Property== 1).DoThing<MyItem, MyNewItem>();

codes.Where should result in an IQueryable< T > output, it's the normal System.Linq namespace.

Results in:

'IEnumerable' does not contain a definition for 'DoThing' and no extension method 'DoThing' accepting a first argument of type 'IEnumerable' could be found (are you missing a using directive or an assembly reference?)

I needed to specify both Types, T and R, as it turns out.

Thank you, all for the help!

Upvotes: 0

Views: 211

Answers (2)

Eric Lippert
Eric Lippert

Reputation: 659974

You cannot do partial method type inference in C#. It would be nice if you could, but you can't. Your choices are to either provide the entire list of type arguments for the method call, or none of them and have them deduced.

In your case type inference will never deduce the type of R because type inference only looks at arguments and formals and there is no formal that uses R.

Looking more specifically at your scenario: I cannot for the life of me see what the body of your method could possibly be; it must create a sequence of R out of a sequence of T. OK, let's suppose T is Giraffe and R is Comparer<Nullable<Rectangle>>. How on earth are you going to get a bunch of nullable rectangle comparers out of a bunch of giraffes?

You are almost certainly doing something very wrong here. Typically you would provide a function to do that. That's why the signature of Select is

public static IEnumerable<R> Select<A, R>(
  this IEnumerable<A> items, 
  Func<A, R> projection)

Now there is enough compile time information for the compiler to deduce both A and R from the call site arguments, and there is a way to get a sequence of R out of a sequence of A, by calling the projection on each A.

Upvotes: 3

pm100
pm100

Reputation: 50110

you must either specify no Types or all of them

do this

List<MyNewItem> newValues = codes.Where(o => o.Property== 1).DoThing();

that wont work with the code you show (cos it doesnt return anything) but if you fix it it probably will. Else do this

List<MyNewItem> newValues = codes.Where(o => o.Property== 1).DoThing<MyNewItem, MyItem>();

Upvotes: 3

Related Questions