我如何为
目标是使扩展方法适用于所有
IEnumerable<T>
定义一个扩展方法,它返回IEnumerable<T>
?目标是使扩展方法适用于所有
IEnumerable
和IEnumerable<T>
,其中T
可以是匿名类型。IEnumerable<T>
定义一个扩展方法,它返回IEnumerable<T>
?IEnumerable
和IEnumerable<T>
,其中T
可以是匿名类型。编写任何迭代器最简单的方法是使用迭代器块,例如:
static IEnumerable<T> Where<T>(this IEnumerable<T> data, Func<T, bool> predicate)
{
foreach(T value in data)
{
if(predicate(value)) yield return value;
}
}
yield return
",它将方法转化为一个迭代器块,并由编译器生成执行相同操作的枚举器(IEnumerator<T>
)。当调用时,泛型类型推断会自动处理T
,因此您只需要:int[] data = {1,2,3,4,5};
var odd = data.Where(i=>i%2 != 0);
var odd = data.Where<int>(i=>i%2 != 0);
IEnumerable
,最简单的方法是让调用者先使用 .Cast<T>(...)
或 .OfType<T>(...)
来获取一个 IEnumerable<T>
。你可以将 this IEnumerable
传递给上述方法,但调用者必须自己指定 T
,而不能让编译器推断。对于匿名类型,你不能使用此方法,因此结论是:不要在匿名类型中使用非泛型的 IEnumerable
。T
(当然,你也不能为匿名类型指定)。在这种情况下,通常可以重构成另一种可由编译器使用推断的签名(例如通过一个传递方法),但你需要发布实际代码来提供答案。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);
}
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;
}
}
}
}
List<T>
,而是只需使用 "yield return 元素" 而不是 Add。 - Marc Gravell