更新时间:2022-06-21 03:19:08
yield
上下文关键字实际上在这里做了很多.
The yield
contextual keyword actually does quite a lot here.
该函数返回一个实现 IEnumerable
接口的对象.如果调用函数开始对这个对象进行foreach
,则该函数将再次被调用,直到它产生".这是C# 2.0 中引入的语法糖.在早期版本中,您必须创建自己的 IEnumerable
和 IEnumerator
对象才能执行此类操作.
The function returns an object that implements the IEnumerable<object>
interface. If a calling function starts foreach
ing 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);
}
}
}
}
}