小编典典

C# 中使用的 yield 关键字是什么?

all

How Can I Expose Only a Fragment of
IList<>
问题中,其中一个答案具有以下代码片段:

IEnumerable<object> FilteredList()
{
    foreach(object item in FullList)
    {
        if(IsItemInPartialList(item))
            yield return item;
    }
}

yield
关键字在那里做什么?我在几个地方和另一个问题上看到过它的引用,但我还没有完全弄清楚它的实际作用。我习惯于从一个线程屈服于另一个线程的意义上考虑屈服,但这在这里似乎无关紧要。


阅读 101

收藏
2022-02-28

共1个答案

小编典典

上下文关键字实际上在yield这里做了很多。

该函数返回一个实现IEnumerable<object>接口的对象。如果调用函数开始foreach对该对象进行调用,则再次调用该函数,直到它“屈服”。这是
C# 2.0 中引入的语法糖。在早期版本中,您必须创建自己的IEnumerable对象IEnumerator来执行此类操作。

理解这样的代码最简单的方法是输入一个例子,设置一些断点,看看会发生什么。尝试逐步执行此示例:

public void Consumer()
{
    foreach(int i in Integers())
    {
        Console.WriteLine(i.ToString());
    }
}

public IEnumerable<int> Integers()
{
    yield return 1;
    yield return 2;
    yield return 4;
    yield return 8;
    yield return 16;
    yield return 16777216;
}

单步执行该示例时,您会发现第一个调用Integers()返回1。第二次调用返回2,该行yield return 1不再执行。

这是一个真实的例子:

public IEnumerable<T> Read<T>(string sql, Func<IDataReader, T> make, params object[] parms)
{
    using (var connection = CreateConnection())
    {
        using (var command = CreateCommand(CommandType.Text, sql, connection, parms))
        {
            command.CommandTimeout = dataBaseSettings.ReadCommandTimeout;
            using (var reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    yield return make(reader);
                }
            }
        }
    }
}
2022-02-28