为IEnumerable <T>定义一个扩展方法,它返回IEnumerable <T>?

Sha*_*bie 26 .net c# extension-methods

如何定义IEnumerable<T>返回的扩展方法IEnumerable<T>?目标是使扩展方法适用于所有人IEnumerable,IEnumerable<T>其中T可以是匿名类型.

Mar*_*ell 41

编写任何迭代器的最简单方法是使用迭代器块,例如:

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

这里的关键是" yield return",它将方法转换为迭代器块,编译器生成一个枚举器(IEnumerator<T>),它执行相同的操作.调用时,泛型类型推断会T自动处理,因此您只需要:

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

以上可以与匿名类型一起使用就好了.

你可以,你可以指定T你想要的(只要它不是匿名的):

var odd = data.Where<int>(i=>i%2 != 0);
Run Code Online (Sandbox Code Playgroud)

Re IEnumerable(非泛型),最简单的方法是让调用者使用.Cast<T>(...).OfType<T>(...)获得IEnumerable<T>第一个.您可以在this IEnumerable上面传入,但调用者必须指定T自己,而不是让编译器推断它.你不能将它T作为匿名类型使用,所以这里的道德是:不要使用IEnumerable匿名类型的非泛型形式.

有一些稍微复杂的方案,其中方法签名使得编译器无法识别T(当然,您无法为匿名类型指定它).在这些情况下,通常可以重新考虑编译器可以与推理一起使用的不同签名(可能通过pass-thru方法),但是您需要发布实际代码以在此处提供答案.


(更新)

在讨论之后,这里有一种利用Cast<T>匿名类型的方法.关键是提供一个可用于类型推断的参数(即使从不使用参数).例如:

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);
}
Run Code Online (Sandbox Code Playgroud)


How*_*ley 6

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;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)