geo*_*ker 11 .net c# yield yield-return
我希望能够对我最近在调试器中完成的一个片段做一些澄清,但是根本无法理解.
我正在PluralSight上学习C#课程,目前的主题是关于并使用关键字返回a .yieldIEnumerable<T>
我有这个过于基本的函数,它返回一个(一个带有的简单类,和)的IEnumerable集合:VendorsIdCompanyNameEmail
public IEnumerable<Vendor> RetrieveWithIterator()
{
this.Retrieve(); // <-- I've got a breakpoint here
foreach(var vendor in _vendors)
{
Debug.WriteLine($"Vendor Id: {vendor.VendorId}");
yield return vendor;
}
}
Run Code Online (Sandbox Code Playgroud)
我在单元测试中得到了这个代码,我用它来测试函数:
var vendorIterator = repository.RetrieveWithIterator(); // <-- Why don't it enter function?
foreach (var item in vendorIterator) // <-- But starts here?
{
Debug.WriteLine(item);
}
var actual = vendorIterator.ToList();
Run Code Online (Sandbox Code Playgroud)
我真的无法理解,我确信很多初学者都遇到了同样的问题,这就是为什么初始调用RetrieveWithIterator不会启动函数,而是在我们开始迭代其返回的IEnumerable集合时开始(见评论).
InB*_*een 14
这称为延迟执行,yield是懒惰的,只能按需要运行.
这有很多优点,其中之一就是你可以创建看似无限的枚举:
public IEnumerable<int> InfiniteOnes()
{
while (true)
yield 1;
}
Run Code Online (Sandbox Code Playgroud)
现在想象如下:
var infiniteOnes = InfiniteOnes();
Run Code Online (Sandbox Code Playgroud)
会急切地执行,你会有一个StackOverflow非常愉快的例外.
另一方面,因为它的懒惰,你可以做到以下几点:
var infiniteOnes = InfiniteOnes();
//.... some code
foreach (var one in infiniteOnes.Take(100)) { ... }
Run Code Online (Sandbox Code Playgroud)
然后,
foreach (var one in infiniteOnes.Take(10000)) { ... }
Run Code Online (Sandbox Code Playgroud)
迭代器块只在需要时运行; 当枚举被迭代时,而不是之前,而不是之后.
来自 msdn:
延迟执行意味着表达式的计算被延迟到实际需要它的实现值。当您必须操作大型数据集合时,延迟执行可以极大地提高性能,尤其是在包含一系列链式查询或操作的程序中。在最好的情况下,延迟执行只允许通过源集合进行一次迭代。
当在迭代器块中使用时,yield 关键字(以 yield-return 语句的形式)在 C# 语言中直接支持延迟执行。这样的迭代器必须返回类型IEnumerator或IEnumerator<T>(或派生类型)的集合。
var vendorIterator = repository.RetrieveWithIterator(); // <-- Lets deferred the execution
foreach (var item in vendorIterator) // <-- execute it because we need it
{
Debug.WriteLine(item);
}
var actual = vendorIterator.ToList();
Run Code Online (Sandbox Code Playgroud)
当您编写实现延迟执行的方法时,您还必须决定是使用惰性求值还是急切求值来实现该方法。
惰性求值通常会产生更好的性能,因为它在整个集合求值过程中平均分配开销处理,并最大限度地减少临时数据的使用。当然,对于某些操作,除了实现中间结果之外别无选择。
| 归档时间: |
|
| 查看次数: |
7795 次 |
| 最近记录: |