[英]Chaining Extension methods in C#
是否可以创建一个扩展方法来返回调用该扩展方法的实例?
我想为从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);
编辑:只是想清楚一点,我希望有一个通用的约束解决方案。
如果需要返回特定类型,则可以使用通用约束:
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
(尽管它不会绑定到其他扩展方法,所以它不适用于链接)。
虽然我没有开放VS来尝试此操作,但应该遵循以下方法:
public static TCollection AddItem<TCollection, TItem>(TCollection collection,
TItem itemToAdd)
where TCollection : ICollection<TItem>
{
collection.Add(itemToAdd);
return collection;
}
您似乎有两个相互矛盾的目标,而这取决于您希望扩展方法返回什么:
从您的示例用法中,此处引用:
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();
编辑:只是想清楚一点,我希望有一个通用的约束解决方案。
在这种情况下,您很不走运,因为返回类型转换可以是协变的,但不是协变的(即,您不能从ICollection<T>
隐式转换为List<T>
),因此,如果没有通用的返回类型,则无法完成。
无论如何指定2个类型参数有什么问题? 您可以通过提供给函数的参数来推断它们,因此您甚至不会在调用代码中真正注意到它们。
只需返回ICollection<T>
而不是object
,一切都应该按照您的预期工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.