C# 在方法调用时或枚举响应时是否枚举IEnumerable
我想知道在调用方法或枚举方法的返回时,是否枚举了方法的IEnumerable参数,假设我们有以下代码:C# 在方法调用时或枚举响应时是否枚举IEnumerable,c#,ienumerable,C#,Ienumerable,我想知道在调用方法或枚举方法的返回时,是否枚举了方法的IEnumerable参数,假设我们有以下代码: IEnumerable进程列表(IEnumerable列表) { foreach(列表中的var元素) { 收益返回流程要素(要素); } } 我最好奇的是如何编写类似Linq的扩展。只有在枚举了ProcessList(enumerable)的结果时才会枚举list(enum2): static void Main(string[] args) { var enumerable =
IEnumerable进程列表(IEnumerable列表)
{
foreach(列表中的var元素)
{
收益返回流程要素(要素);
}
}
我最好奇的是如何编写类似Linq的扩展。只有在枚举了ProcessList
(enumerable
)的结果时才会枚举list
(enum2
):
static void Main(string[] args)
{
var enumerable = Enum1();
Console.WriteLine("Enum1 retrieved");
var enum2 = Enum2(enumerable);
Console.WriteLine("Enum2 called");
foreach (var e in enum2)
{
Console.WriteLine(e);
}
}
private static IEnumerable<string> Enum1()
{
Console.WriteLine("Enum1");
yield return "foo";
}
private static IEnumerable<string> Enum2(IEnumerable<string> enumerable)
{
Console.WriteLine("Enum2");
foreach (var s in enumerable)
{
yield return s;
}
}
最后三行仅在进入foreach
循环时打印。仅在枚举ProcessList
(enum2
)的结果时才枚举列表(enumable
):
static void Main(string[] args)
{
var enumerable = Enum1();
Console.WriteLine("Enum1 retrieved");
var enum2 = Enum2(enumerable);
Console.WriteLine("Enum2 called");
foreach (var e in enum2)
{
Console.WriteLine(e);
}
}
private static IEnumerable<string> Enum1()
{
Console.WriteLine("Enum1");
yield return "foo";
}
private static IEnumerable<string> Enum2(IEnumerable<string> enumerable)
{
Console.WriteLine("Enum2");
foreach (var s in enumerable)
{
yield return s;
}
}
最后三行仅在进入foreach
循环时打印。使用yield
关键字意味着此代码片段将仅在需要时进行计算,以提供您使用的结果。换句话说,这不会导致评估:
var processed = ProcessList(unprocessed);
结果列表的内容无关紧要,因此不会对其进行评估。但是,如果您这样做:
var processed = ProcessList(unprocessed).ToList();
var processed = ProcessList(unprocessed);
foreach (var x in processed)
{
DoSomething(x);
}
var processed = ProcessList(unprocessed);
foreach (var x in processed.Take(10))
{
DoSomething(x);
}
这将要求它计算IEnumerable
,这将导致它运行您的代码。同样,如果您这样做:
var processed = ProcessList(unprocessed).ToList();
var processed = ProcessList(unprocessed);
foreach (var x in processed)
{
DoSomething(x);
}
var processed = ProcessList(unprocessed);
foreach (var x in processed.Take(10))
{
DoSomething(x);
}
它将依次为每个元素运行ProcessElement()
方法。若要进一步了解这一点,请执行以下操作:
var processed = ProcessList(unprocessed).ToList();
var processed = ProcessList(unprocessed);
foreach (var x in processed)
{
DoSomething(x);
}
var processed = ProcessList(unprocessed);
foreach (var x in processed.Take(10))
{
DoSomething(x);
}
因为您只使用结果列表的前10项,所以它将只对这10项运行ProcessElement()
方法。其余的代码只会在您使用它们时进行评估。使用yield
关键字意味着这段代码只会在需要时进行评估,以提供您使用的结果。换句话说,这不会导致评估:
var processed = ProcessList(unprocessed);
结果列表的内容无关紧要,因此不会对其进行评估。但是,如果您这样做:
var processed = ProcessList(unprocessed).ToList();
var processed = ProcessList(unprocessed);
foreach (var x in processed)
{
DoSomething(x);
}
var processed = ProcessList(unprocessed);
foreach (var x in processed.Take(10))
{
DoSomething(x);
}
这将要求它计算IEnumerable
,这将导致它运行您的代码。同样,如果您这样做:
var processed = ProcessList(unprocessed).ToList();
var processed = ProcessList(unprocessed);
foreach (var x in processed)
{
DoSomething(x);
}
var processed = ProcessList(unprocessed);
foreach (var x in processed.Take(10))
{
DoSomething(x);
}
它将依次为每个元素运行ProcessElement()
方法。若要进一步了解这一点,请执行以下操作:
var processed = ProcessList(unprocessed).ToList();
var processed = ProcessList(unprocessed);
foreach (var x in processed)
{
DoSomething(x);
}
var processed = ProcessList(unprocessed);
foreach (var x in processed.Take(10))
{
DoSomething(x);
}
因为您只使用结果列表的前10项,所以它将只对这10项运行ProcessElement()
方法。其余部分只有在您开始使用时才会进行评估。您可以通过在回路中放置制动点来了解自己。但我的最佳猜测是,它是在枚举结果时枚举的。如果您想创建类似Linq的扩展方法,应该由Jon Skeet检查。您可以编写返回无限长序列的枚举(例如,,而(true)返回1;
)您将能够调用返回枚举的方法,而不会花费无限长的时间。只有“枚举枚举器”将开始遍历循环。谢谢!虽然我可以自己测试一下,但我认为这些答案对其他人来说是一个很好的参考。你可以通过在你的循环中放置一个制动点来发现你自己。但我的最佳猜测是,它是在枚举结果时枚举的。如果您想创建类似Linq的扩展方法,应该由Jon Skeet检查。您可以编写返回无限长序列的枚举(例如,,而(true)返回1;
)您将能够调用返回枚举的方法,而不会花费无限长的时间。只有“枚举枚举器”将开始遍历循环。谢谢!虽然我可以自己测试一下,但我认为这些答案对其他人来说是一个很好的参考。