简体   繁体   English

为IEnumerable定义扩展方法 <T> 返回IEnumerable <T> ?

[英]Define an Extension Method for IEnumerable<T> which returns IEnumerable<T>?

How do I define an Extension Method for IEnumerable<T> which returns IEnumerable<T> ? 如何为IEnumerable<T>定义一个返回IEnumerable<T>的扩展方法? The goal is to make the Extension Method available for all IEnumerable and IEnumerable<T> where T can be an anonymous type. 目标是使扩展方法可用于所有IEnumerableIEnumerable<T> ,其中T可以是匿名类型。

The easiest way to write any iterator is with an iterator block, for example: 编写任何迭代器的最简单方法是使用迭代器块,例如:

static IEnumerable<T> Where<T>(this IEnumerable<T> data, Func<T, bool> predicate)
{
    foreach(T value in data)
    {
        if(predicate(value)) yield return value;
    }
}

The key here is the " yield return ", which turns the method into an iterator block, with the compiler generating an enumerator ( IEnumerator<T> ) that does the same. 这里的关键是“ yield return ”,它将方法转换为迭代器块,编译器生成一个枚举器( IEnumerator<T> ),它执行相同的操作。 When called, generic type inference handles the T automatically, so you just need: 调用时,泛型类型推断自动处理T ,因此您只需要:

int[] data = {1,2,3,4,5};
var odd = data.Where(i=>i%2 != 0);

The above can be used with anonymous types just fine. 以上可以与匿名类型一起使用就好了。

You can, of coure, specify the T if you want (as long as it isn't anonymous): 如果你愿意,你可以指定T (只要它不是匿名的):

var odd = data.Where<int>(i=>i%2 != 0);

Re IEnumerable (non-generic), well, the simplest approach is for the caller to use .Cast<T>(...) or .OfType<T>(...) to get an IEnumerable<T> first. Re IEnumerable (非泛型),最简单的方法是让调用者首先使用.Cast<T>(...).OfType<T>(...)来获取IEnumerable<T> You can pass in this IEnumerable in the above, but the caller will have to specify T themselves, rather than having the compiler infer it. 你可以在上面传入this IEnumerable ,但是调用者必须自己指定T ,而不是让编译器推断它。 You can't use this with T being an anonymous type, so the moral here is: don't use the non-generic form of IEnumerable with anonymous types. 你不能使用T作为匿名类型,所以这里的道德是:不要使用匿名类型的IEnumerable的非泛型形式。

There are some slightly more complex scenarios where the method signature is such that the compiler can't identify the T (and of course you can't specify it for anonymous types). 有一些稍微复杂的方案,其中方法签名使得编译器无法识别T (当然,您无法为匿名类型指定它)。 In those cases, it is usually possible to re-factor into a different signature that the compiler can use with inference (perhaps via a pass-thru method), but you'd need to post actual code to provide an answer here. 在这些情况下,通常可以重新考虑编译器可以与推理一起使用的不同签名(可能通过pass-thru方法),但是您需要发布实际代码以在此处提供答案。


(updated) (更新)

Following discussion, here's a way to leverage Cast<T> with anonymous types. 在讨论之后,这里有一种方法可以将Cast<T>与匿名类型结合使用。 The key is to provide an argument that can be used for the type inference (even if the argument is never used). 关键是提供一个可用于类型推断的参数(即使从不使用参数)。 For example: 例如:

static void Main()
{
    IEnumerable data = new[] { new { Foo = "abc" }, new { Foo = "def" }, new { Foo = "ghi" } };
    var typed = data.Cast(() => new { Foo = "never used" });
    foreach (var item in typed)
    {
        Console.WriteLine(item.Foo);
    }
}

// note that the template is not used, and we never need to pass one in...
public static IEnumerable<T> Cast<T>(this IEnumerable source, Func<T> template)
{
    return Enumerable.Cast<T>(source);
}
using System;
using System.Collections.Generic;

namespace ExtentionTest {
    class Program {
        static void Main(string[] args) {

            List<int> BigList = new List<int>() { 1,2,3,4,5,11,12,13,14,15};
            IEnumerable<int> Smalllist = BigList.MyMethod();
            foreach (int v in Smalllist) {
                Console.WriteLine(v);
            }
        }

    }

    static class EnumExtentions {
        public static IEnumerable<T> MyMethod<T>(this IEnumerable<T> Container) {
            int Count = 1;
            foreach (T Element in Container) {
                if ((Count++ % 2) == 0)
                    yield return Element;
            }
        }
    }
}

This post may help you to get started: How do you write a C# Extension Method for a Generically Typed Class . 这篇文章可以帮助您入门: 如何为一般类型的类编写C#扩展方法 I'm not sure if it is exactly what you are looking for but it might get you started. 我不确定它是不是你正在寻找的,但它可能会让你开始。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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