C# 为 IEnumerable<T> 定义一个扩展方法,它返回 IEnumerable<T>?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/277150/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Define an Extension Method for IEnumerable<T> which returns IEnumerable<T>?
提问by SharePoint Newbie
How do I define an Extension Method for IEnumerable<T>
which returns IEnumerable<T>
?
The goal is to make the Extension Method available for all IEnumerable
and IEnumerable<T>
where T
can be an anonymous type.
如何定义IEnumerable<T>
返回的扩展方法IEnumerable<T>
?我们的目标是使扩展方法适用于所有IEnumerable
并IEnumerable<T>
在那里T
可以是匿名类型。
采纳答案by Marc Gravell
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. When called, generic type inference handles the T
automatically, so you just need:
这里的关键是“ yield return
”,它将方法变成一个迭代器块,编译器生成一个枚举器 ( IEnumerator<T>
) 来做同样的事情。调用时,泛型类型推断会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. 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. 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.
Re IEnumerable
(非通用),好吧,最简单的方法是让调用者使用.Cast<T>(...)
或.OfType<T>(...)
获取IEnumerable<T>
第一个。您可以传入this IEnumerable
上面的内容,但调用者必须指定T
自己,而不是让编译器推断它。您不能将它与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). In those cases, it is usually possible to re-factor into a different signature that the compiler canuse with inference (perhaps via a pass-thru method), but you'd need to post actual code to provide an answer here.
有一些稍微复杂的场景,其中方法签名使得编译器无法识别T
(当然你不能为匿名类型指定它)。在这些情况下,通常可以重新分解为编译器可以用于推理的不同签名(可能通过传递方法),但您需要发布实际代码以在此处提供答案。
(updated)
(更新)
Following discussion, here's a way to leverage Cast<T>
with anonymous types. The key is to provide an argument that can be used for the type inference (even if the argument is never used). For example:
经过讨论,这里有一种利用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);
}
回答by Nathan W
This post may help you to get started:How do you write a C# Extension Method for a Generically Typed Class. I'm not sure if it is exactly what you are looking for but it might get you started.
这篇文章可能会帮助您入门:如何为泛型类编写 C# 扩展方法。我不确定它是否正是您正在寻找的,但它可能会让您开始。
回答by Howard Pinsley
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;
}
}
}
}