收益率在现实生活中有哪些应用?

发布于 2024-07-04 08:05:59 字数 108 浏览 8 评论 0原文

我知道 yield 的作用,并且我看过一些例子,但我想不出现实生活中的应用程序,你用它来解决一些具体问题吗?

(理想情况下是一些无法通过其他方式解决的问题)

I know what yield does, and I've seen a few examples, but I can't think of real life applications, have you used it to solve some specific problem?

(Ideally some problem that cannot be solved some other way)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

素年丶 2024-07-11 08:05:59

Yield 的另一个很好的用途是对 IEnumerable 的元素执行函数并返回不同类型的结果,例如:

public delegate T SomeDelegate(K obj);

public IEnumerable<T> DoActionOnList(IEnumerable<K> list, SomeDelegate action)
{
    foreach (var i in list)
        yield return action(i);
}

Another good use for yield is to perform a function on the elements of an IEnumerable and to return a result of a different type, for example:

public delegate T SomeDelegate(K obj);

public IEnumerable<T> DoActionOnList(IEnumerable<K> list, SomeDelegate action)
{
    foreach (var i in list)
        yield return action(i);
}
世界如花海般美丽 2024-07-11 08:05:59

使用yield可以防止向下转型为具体类型。 这可以方便地确保集合的使用者不会操纵它。

Using yield can prevent downcasting to a concrete type. This is handy to ensure that the consumer of the collection doesn't manipulate it.

您还可以使用 yield return 将一系列函数结果视为列表。 例如,考虑一家每两周向员工支付工资的公司。 人们可以使用以下代码以列表形式检索工资单日期的子集:

void Main()
{
    var StartDate = DateTime.Parse("01/01/2013");
    var EndDate = DateTime.Parse("06/30/2013");
    foreach (var d in GetPayrollDates(StartDate, EndDate)) {
        Console.WriteLine(d);
    }
}

// Calculate payroll dates in the given range.
// Assumes the first date given is a payroll date.
IEnumerable<DateTime> GetPayrollDates(DateTime startDate, DateTime endDate, int     daysInPeriod = 14) {
    var thisDate = startDate;
    while (thisDate < endDate) {
        yield return thisDate;
        thisDate = thisDate.AddDays(daysInPeriod);
    }
}

You can also use yield return to treat a series of function results as a list. For instance, consider a company that pays its employees every two weeks. One could retrieve a subset of payroll dates as a list using this code:

void Main()
{
    var StartDate = DateTime.Parse("01/01/2013");
    var EndDate = DateTime.Parse("06/30/2013");
    foreach (var d in GetPayrollDates(StartDate, EndDate)) {
        Console.WriteLine(d);
    }
}

// Calculate payroll dates in the given range.
// Assumes the first date given is a payroll date.
IEnumerable<DateTime> GetPayrollDates(DateTime startDate, DateTime endDate, int     daysInPeriod = 14) {
    var thisDate = startDate;
    while (thisDate < endDate) {
        yield return thisDate;
        thisDate = thisDate.AddDays(daysInPeriod);
    }
}
霊感 2024-07-11 08:05:59

Enumerable 类上的 LINQ 运算符被实现为使用yield 语句创建的迭代器。 它允许您链接 Select() 和Where() 等操作,而无需实际枚举任何内容,直到您在循环中实际使用枚举器(通常通过使用foreach 语句)。 此外,由于如果您决定在收集过程中停止,则在调用 IEnumerator.MoveNext() 时仅计算一个值,因此您将节省计算所有结果的性能损失。

迭代器还可以用于实现其他类型的惰性求值,其中仅在需要时才对表达式求值。 您还可以使用yield来获得更奇特的东西,例如协程。

LINQ's operators on the Enumerable class are implemented as iterators that are created with the yield statement. It allows you to chain operations like Select() and Where() without actually enumerating anything until you actually use the enumerator in a loop, typically by using the foreach statement. Also, since only one value is computed when you call IEnumerator.MoveNext() if you decide to stop mid-collection, you'll save the performance hit of calculating all of the results.

Iterators can also be used to implement other kinds of lazy evaluation where expressions are evaluated only when you need it. You can also use yield for more fancy stuff like coroutines.

橘虞初梦 2024-07-11 08:05:59

一个有趣的用途是作为异步编程的机制,特别是用于执行多个步骤并在每个步骤中需要相同数据集的任务。 这方面的两个示例是 Jeffery Richters AysncEnumerator 第 1 部分第 2 部分。 并发和协调运行时 (CCR) 也利用了此技术CCR 迭代器。

One interesting use is as a mechanism for asynchronous programming esp for tasks that take multiple steps and require the same set of data in each step. Two examples of this would be Jeffery Richters AysncEnumerator Part 1 and Part 2. The Concurrency and Coordination Runtime (CCR) also makes use of this technique CCR Iterators.

暗藏城府 2024-07-11 08:05:59

实际上,我在我的网站上以非传统方式使用它 IdeaPipe

public override IEnumerator<T> GetEnumerator()
{
    // goes through the collection and only returns the ones that are visible for the current user
    // this is done at this level instead of the display level so that ideas do not bleed through
    // on services
    foreach (T idea in InternalCollection)
        if (idea.IsViewingAuthorized)
            yield return idea;
}

所以基本上它会检查查看该想法当前是否已获得授权,并且如果是,则返回该想法。 如果不是,则直接跳过。 这允许我缓存想法,但仍然向授权的用户显示想法。 否则,我每次都必须根据权限重新拉取它们,而它们每 1 小时才重新排名一次。

actually I use it in a non traditional way on my site IdeaPipe

public override IEnumerator<T> GetEnumerator()
{
    // goes through the collection and only returns the ones that are visible for the current user
    // this is done at this level instead of the display level so that ideas do not bleed through
    // on services
    foreach (T idea in InternalCollection)
        if (idea.IsViewingAuthorized)
            yield return idea;
}

so basically it checks if viewing the idea is currently authorized and if it is it returns the idea. If it isn't, it is just skipped. This allows me to cache the Ideas but still display the ideas to the users that are authorized. Else I would have to re pull them each time based on permissions, when they are only re-ranked every 1 hour.

ゝ偶尔ゞ 2024-07-11 08:05:59

我意识到这是一个老问题(乔恩·斯基特之前?),但我最近一直在考虑这个问题。 不幸的是,这里当前的答案(在我看来)没有提到yield语句最明显的优点。

yield 语句的最大好处是它允许您迭代非常大的列表,并且比使用标准列表更有效地使用内存。

例如,假设您有一个返回 100 万行的数据库查询。 您可以使用 DataReader 检索所有行并将它们存储在 List 中,因此需要 list_size * row_size 字节的内存。

或者,您可以使用yield 语句创建一个迭代器,并且一次只在内存中存储一​​行。 实际上,这使您能够为大量数据提供“流”功能。

此外,在使用 Iterator 的代码中,您可以使用简单的 foreach 循环,并且可以根据需要决定从循环中跳出。 如果您确实提前中断,那么当您只需要前 5 行时(例如),您就不会强制检索整个数据集。

关于:

Ideally some problem that cannot be solved some other way

yield 语句不会为您提供使用自己的自定义迭代器实现无法完成的任何操作,但它使您无需编写所需的通常复杂的代码。 很少有问题(如果有的话)不能通过多种方法解决。

以下是一些提供更多详细信息的最新问题和解答:

收益关键字增值?

yield 在 LINQ 之外有用吗?

I realise this is an old question (pre Jon Skeet?) but I have been considering this question myself just lately. Unfortunately the current answers here (in my opinion) don't mention the most obvious advantage of the yield statement.

The biggest benefit of the yield statement is that it allows you to iterate over very large lists with much more efficient memory usage then using say a standard list.

For example, let's say you have a database query that returns 1 million rows. You could retrieve all rows using a DataReader and store them in a List, therefore requiring list_size * row_size bytes of memory.

Or you could use the yield statement to create an Iterator and only ever store one row in memory at a time. In effect this gives you the ability to provide a "streaming" capability over large sets of data.

Moreover, in the code that uses the Iterator, you use a simple foreach loop and can decide to break out from the loop as required. If you do break early, you have not forced the retrieval of the entire set of data when you only needed the first 5 rows (for example).

Regarding:

Ideally some problem that cannot be solved some other way

The yield statement does not give you anything you could not do using your own custom iterator implementation, but it saves you needing to write the often complex code needed. There are very few problems (if any) that can't solved more than one way.

Here are a couple of more recent questions and answers that provide more detail:

Yield keyword value added?

Is yield useful outside of LINQ?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文