Как мне создать универсальный метод с вложенными T? - PullRequest
3 голосов
/ 09 апреля 2011

У меня был общий метод расширения

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

который я назвал используя

myStatefulSetOfStuff = myStatefulSetOfStuff.Replace(GetNewSetOfStuff());

Однако я понял, что мой метод будет работать со всеми коллекциями, которые реализуют ICollection, поэтому я изменил его на

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

Однако теперь метод возвращает IColllection, что вынуждает меня написать вызов как:

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

Как мне переписать мой метод, чтобы мне не нужно было .ToList() при вызове?

EDIT: Кажется, здесь есть некоторая путаница, поэтому я постараюсь прояснить это. У меня есть список. Я хочу выполнить операцию в этом списке с новым списком. Нет проблем. И я выяснил, как вернуть List с помощью метода расширения.

Но я понял, эй, фактический код в Replace () не относится только к спискам, он может применяться к любой коллекции. Поэтому я изменил Replace, чтобы вернуть ICollection. Это тогда заставляет вызывающий метод выглядеть как

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

или

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

и т.д.

Но я не хочу говорить ToList, ToArray и т. Д., Я хочу, чтобы метод просто выводил правильный тип возврата из исходного объекта. Так что я могу сказать

var newStuff = left.Replace(right);

и newStuff будут того же типа, что и левый. Right тоже будет того же типа.

Ответы [ 2 ]

9 голосов
/ 09 апреля 2011

Попробуйте следующее

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

Вот пример использования

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

К сожалению, в этом сценарии общие параметры действительно необходимы (не удается получить вывод типа для этой операции)конкретный сценарий)

РЕДАКТИРОВАТЬ

Мой ответ основан на некотором неправильном прочтении вопроса.Я думал, что целью было передать тип source возвращаемому типу метода.При дальнейшем перечитывании кажется, что вместо этого вы хотите передать любой источник и вернуть List во всех случаях.В этом случае я предлагаю вам взглянуть на ответ Рида.

3 голосов
/ 09 апреля 2011

Если вам нужно, чтобы он всегда возвращал IList<T>,, просто измените его на:

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

И поместите вызов .ToList() в свой метод расширения (если он уже не создает список внутри).

При этом вы можете "вкладывать" это, имея два параметра типа, если вы хотите это сделать.

...