C# 中的链接扩展方法

发布于 2024-09-09 04:53:37 字数 470 浏览 9 评论 0原文

是否可以创建一个返回调用扩展方法的实例的扩展方法?

我希望有一个扩展方法,用于从 ICollection 继承并返回对象的任何内容。很像 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);

编辑:只是想清楚我希望有一个通用约束解决方案。

Is it possible to create an extension method that returns the instance that is invoking the extension method?

I would like to have an extension method for anything that inherits from ICollection<T>, returns the object. Much like how jQuery always returns the jquery object.

public static object AddItem<T>(this ICollection<T> collection, T itemToAdd)
{
    collection.Add(itemToAdd);
    return collection;
{

I imagine something like above, but I am not sure how to get back to the parent to the "this" object type for use of something like this:

List<int> myInts = new List<int>().AddItem(5);

EDIT: Just wanted to be clear that i was hoping for a single generic constraint solution.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

浪推晚风 2024-09-16 04:53:37

如果需要返回特定类型,可以使用通用约束:

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 支持动态,因此您可以这样做:

public static dynamic AddItem<T>(this ICollection<T> collection, T itemToAdd)
{
    collection.Add(itemToAdd);
    return collection;
}

但是,我确实推荐通用约束版本,因为它更类型安全、更高效,并且允许对返回类型进行 IntelliSense。在更复杂的场景中,通用约束并不总是能够表达您的需求;在这些情况下,可以使用dynamic(尽管它不会绑定到其他扩展方法,因此它不能很好地与链接配合使用)。

If you need to return the specific type, you can use a generic constraint:

public static TCollection AddItem<TCollection, TElement>(
    this TCollection collection,
    TElement itemToAdd)
    where TCollection : ICollection<TElement>
{
    collection.Add(itemToAdd);
    return collection;
}

I tested this and it works in VS2010.

Update (regarding jQuery):

jQuery chaining works very well because JavaScript uses dynamic typing. C# 4.0 supports dynamic, so you can do this:

public static dynamic AddItem<T>(this ICollection<T> collection, T itemToAdd)
{
    collection.Add(itemToAdd);
    return collection;
}

However, I do recommend the generic constraint version, since it is more type-safe, more efficient, and allows IntelliSense on the returned type. In more complex scenarios, generic constraints aren't always capable of expressing what you need; in those cases, dynamic can be used (though it won't bind to additional extension methods, so it doesn't work well with chaining).

裂开嘴轻声笑有多痛 2024-09-16 04:53:37

虽然我没有打开 VS 来尝试此操作,但以下内容应该可以工作:

public static TCollection AddItem<TCollection, TItem>(TCollection collection, 
                                                      TItem itemToAdd) 
where TCollection : ICollection<TItem>
{
    collection.Add(itemToAdd);
    return collection;
}

While I don't have VS open to try this, something along these lines should work:

public static TCollection AddItem<TCollection, TItem>(TCollection collection, 
                                                      TItem itemToAdd) 
where TCollection : ICollection<TItem>
{
    collection.Add(itemToAdd);
    return collection;
}
红颜悴 2024-09-16 04:53:37

您似乎有两个相互冲突的目标,这取决于您希望扩展方法返回什么:

  • 调用扩展方法的实例(集合)
  • 或添加到集合中的项目

从您的示例用法中引用,此处引用:

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

You seem to have 2 conflicting goals, and it comes down to what do you want your extension method to return:

  • The instance that invoked the extension method (the collection)
  • OR the item that was added to the collection

From your example usage, quoted here:

List<int> myInts = new List<int>().AddItem(5);

You make it look like you want to return the collection. In any case, that assignment still won't work without a cast, since your extension method would need to have a return type of ICollection, like this:

public static ICollection<T> AddItem<T>(this ICollection<T> collection, T itemToAdd)
{
    collection.Add(itemToAdd);
    return collection;
}

That would allow you to do this:

List<int> myList = (List<int>) new List<int>().AddItem(5);

Now if you'd rather return the object that was added, you still shouldn't have a return type of object. You should take advantage of your generic type parameter, and return T, like this:

public static T AddItem<T>(this ICollection<T> collection, T itemToAdd)
{
    collection.Add(itemToAdd);
    return itemToAdd;
}

However, if you're returning the item that was added, you won't be able to chain like this:

List<int> myList = (List<int>) new List<int>().AddItem(5);

, since the return type of AddItem(5) is not ICollection, but it's T (int, in this case). You can still chain though, just off of the value added, like this:

List<int> myList = new List<int>();
myList.AddItem(5).DoSomethingWithMyInt(); // Not very useful in this case

It seems like the first scenario is more useful (returning the collection), because it does allow you chain, right off of the initial assignment statement. Here's a larger example of that:

List<int> myList = (List<int>) new List<int>().AddItem(1).AddItem(2);

Or, if you don't want to cast, you can call ToList() on the ICollection that comes back:

List<int> myList = new List<int>().AddItem(1).AddItem(2).ToList();
韬韬不绝 2024-09-16 04:53:37

编辑:只是想澄清我希望有一个通用的约束解决方案。

在这种情况下,您就不走运了,因为返回类型转换可以是协变的,但不是逆变的(即您不能从 ICollection 隐式转换为 List ),所以如果没有通用返回类型,这是无法完成的。

无论如何指定 2 个类型参数有什么问题吗?它们可以通过您提供给函数的参数来推断,因此您甚至不会在调用代码中真正注意到它们。

EDIT: Just wanted to be clear that i was hoping for a single generic constraint solution.

In this case you're out of luck because return type conversions can be covariant, but not contravariant (i.e. you cannot implicitly convert from ICollection<T> to List<T>), so without a generic return type this cannot be done.

What's wrong with specifying 2 type parameters anyway? They can be inferred by the arguments you provide to the function so you won't even really notice them in your calling code.

心房敞 2024-09-16 04:53:37

只需返回 ICollection 而不是 object ,一切都会按照您的预期工作。

Just return ICollection<T>instead of object and everything should work like you intended it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文