如何使用嵌套T创建通用方法?

时间:2011-04-08 20:28:54

标签: c# generics extension-methods

我有一个通用的扩展方法

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()

编辑: 有些混乱,所以我会试着清理它。我有一份清单。我想用新列表在该列表上执行操作。没问题。我想出了如何使用扩展方法返回List。

但我意识到,嘿,Replace()中的实际代码并不特定于Lists,它可以应用于任何集合。所以我修改了Replace以返回ICollection。这会强制调用方法看起来像

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

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

但我不想说ToList,ToArray等,我希望该方法只是从源对象推断出正确的返回类型。所以我可以说

var newStuff = left.Replace(right);

和newStuff的类型与左边​​相同。右边也是同一类型。

2 个答案:

答案 0 :(得分:9)

尝试以下

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。在这种情况下,我建议你看看里德的答案。

答案 1 :(得分:3)

如果您需要它始终返回IList<T>,,只需将其更改为:

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

.ToList()调用放在扩展方法中(除非它已经在内部创建了一个列表)。

话虽如此,如果您愿意,可以通过两个类型参数“嵌套”它。