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.
精彩评论