Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I create a generic method with nested T's?

I had a generic extension method

public static IList<T> Replace<T>(this IList<T> source, Ilist<T> newList) where T:IStateful

which I called using

myStatefulSetOfStuff = myStatefulSetOfStuff.Replace(GetNewSetOfStuff());

I realized, though, that my method would work on all collections that implement ICollection, so I changed it to

public static ICollection<T> Replace<T>(this ICollection<T> source, ICollection<T> newList) where T:IStateful

However, now the method returns an IColllection, which forces me to write the call as:

myStatefulSetOfStuff = myStatefulSetOfStuff.Replace(GetNewSetOfStuff()).ToList();

How can I re-write my method so that I don't need the .ToList() on my call?

EDIT: There seemes to be some confusion, so I'll try to clear it up. I have a list. I want to perform an operation on that list with a new list. No problem. And I figured out how to return a List with an extension method.

But I realized, hey, the actual code in Replace() isn't specific to Lists, it can apply to any collection. So I modified Replace to return an ICollection. This then forces the calling method to look like

var newStuff = left.Replace(right).ToList()

or

var newStuff = left.Replace(right).ToArray()

etc.

But I don't want to say ToList, ToArray, etc., I want the method to just infer the correct return type from the source object. So I can say

var newStuff = left.Replace(right);

and newStuff will be of the same type as left. Right will be of the same type as well.

like image 623
John Avatar asked Mar 23 '26 07:03

John


1 Answers

Try the following

public static TCollection Replace<TCollection, TItem>(
  this TCollection source,   
  TCollection newList)
    where TCollection : ICollection<TItem>
    where TItem : IStateful

Here's a use case example

interface IStateful { }
class Foo : IStateful { }
static void Test()
{
    ICollection<Foo> left = null, right= null;
    left.Replace<ICollection<Foo>, Foo>(right);
}

Unfortunately the generic parameters do appear necessary in this scenario (can't get type inference to work for this specific scenario)

EDIT

My answer is based off of a bit of a misread of the question. I thought the intent was to flow the type of the source to the return type of the method. Upon further re-reading though it appears you want instead to flow any source and return an List in all cases. In which case I suggest you take a look at Reed's answer.

like image 155
JaredPar Avatar answered Mar 24 '26 20:03

JaredPar