是否可以创建一个返回调用扩展方法的实例的扩展方法?
我想为从ICollection<T>
继承的任何东西都有一个扩展方法,返回该对象。就像jQuery总是返回jquery对象一样。
public static object AddItem<T>(this ICollection<T> collection, T itemToAdd)
{
collection.Add(itemToAdd);
return collection;
{
我想象上面的内容,但我不知道如何回到父母的“this”对象类型来使用这样的东西:
List<int> myInts = new List<int>().AddItem(5);
编辑:只是想明确我希望有一个通用约束解决方案。
答案 0 :(得分:13)
如果需要返回特定类型,可以使用通用约束:
public static TCollection AddItem<TCollection, TElement>(
this TCollection collection,
TElement itemToAdd)
where TCollection : ICollection<TElement>
{
collection.Add(itemToAdd);
return collection;
}
我对此进行了测试,它可以在VS2010中使用。
更新(关于jQuery):
jQuery链接非常有效,因为JavaScript使用动态类型。 C#4.0支持dynamic
,因此您可以这样做:
public static dynamic AddItem<T>(this ICollection<T> collection, T itemToAdd)
{
collection.Add(itemToAdd);
return collection;
}
但是,我建议使用通用约束版本,因为它更加类型安全,更高效,并且允许返回类型的IntelliSense。在更复杂的场景中,通用约束并不总能表达您的需求;在这些情况下,可以使用dynamic
(虽然它不会绑定到其他扩展方法,因此它不适用于链接)。
答案 1 :(得分:4)
虽然我没有打开VS试试这个,但这些方面应该有用:
public static TCollection AddItem<TCollection, TItem>(TCollection collection,
TItem itemToAdd)
where TCollection : ICollection<TItem>
{
collection.Add(itemToAdd);
return collection;
}
答案 2 :(得分:2)
您似乎有两个相互冲突的目标,这取决于您希望您的扩展方法返回什么:
根据您的示例用法,引用此处:
List<int> myInts = new List<int>().AddItem(5);
您看起来好像要返回该集合。在任何情况下,如果没有强制转换,该分配仍然无效,因为您的扩展方法需要具有ICollection的返回类型,如下所示:
public static ICollection<T> AddItem<T>(this ICollection<T> collection, T itemToAdd)
{
collection.Add(itemToAdd);
return collection;
}
这将允许你这样做:
List<int> myList = (List<int>) new List<int>().AddItem(5);
现在,如果您宁愿返回已添加的对象,则仍然不应该返回object
的返回类型。您应该利用您的泛型类型参数,并返回T
,如下所示:
public static T AddItem<T>(this ICollection<T> collection, T itemToAdd)
{
collection.Add(itemToAdd);
return itemToAdd;
}
但是,如果您要返回已添加的项目,则无法像这样链接:
List<int> myList = (List<int>) new List<int>().AddItem(5);
,因为AddItem(5)
的返回类型不是 ICollection,但它是T
(int
,在这种情况下)。你仍然可以链接,只是增加了价值,如下:
List<int> myList = new List<int>();
myList.AddItem(5).DoSomethingWithMyInt(); // Not very useful in this case
似乎第一个场景更有用(返回集合),因为它确实允许你链接,直接从初始赋值语句。这是一个更大的例子:
List<int> myList = (List<int>) new List<int>().AddItem(1).AddItem(2);
或者,如果你不想演员,你可以在回来的ICollection上调用ToList()
:
List<int> myList = new List<int>().AddItem(1).AddItem(2).ToList();
答案 3 :(得分:1)
编辑:只是想明确我希望有一个通用约束解决方案。
在这种情况下,你运气不好,因为返回类型转换可以是协变的,但不是逆变的(即你不能隐式地从ICollection<T>
转换为List<T>
),所以没有通用的返回类型无法完成。
无论如何指定2个类型参数有什么问题?它们可以通过您提供给函数的参数来推断,因此您甚至不会在调用代码中真正注意到它们。
答案 4 :(得分:0)
只需返回ICollection<T>
而不是object
,一切都应该像您预期的那样工作。