且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2022-06-21 03:19:08

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

The yield contextual keyword actually does quite a lot here.

该函数返回一个实现 IEnumerable 接口的对象.如果调用函数开始对这个对象进行foreach,则该函数将再次被调用,直到它产生".这是C# 2.0 中引入的语法糖.在早期版本中,您必须创建自己的 IEnumerableIEnumerator 对象才能执行此类操作.

The function returns an object that implements the IEnumerable<object> interface. If a calling function starts foreaching over this object, the function is called again until it "yields". This is syntactic sugar introduced in C# 2.0. In earlier versions you had to create your own IEnumerable and IEnumerator objects to do stuff like this.

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

The easiest way understand code like this is to type-in an example, set some breakpoints and see what happens. Try stepping through this example:

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 不再执行.

When you step through the example, you'll find the first call to Integers() returns 1. The second call returns 2 and the line yield return 1 is not executed again.

这是一个真实的例子:

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);
                }
            }
        }
    }
}