繁体   English   中英

C#中的链接扩展方法

[英]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,而是Tint ,在这种情况下)。 但是,您仍然可以像添加值一样进行链接,如下所示:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM