开发者

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

开发者 https://www.devze.com 2023-02-23 07:13 出处:网络
I had a generic extension method public static IList<T> Replace<T>(this IList<T> source, Ilist<T> newList) where T:IStateful

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 = myS开发者_如何学运维tatefulSetOfStuff.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.


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.


If you need it to always return IList<T>, just change it to:

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

And put the .ToList() call inside your extension method (unless it's already creating a list internally).

That being said, you can "nest" this by having two type parameters, if you wish to do so.

0

精彩评论

暂无评论...
验证码 换一张
取 消