在“ 如何仅显示IList <>的片段”问题中,答案之一具有以下代码片段:
IEnumerable<object> FilteredList() { foreach(object item in FullList) { if(IsItemInPartialList(item)) yield return item; } }
yield关键字在那里做什么?我已经在几个地方提到过它,还有另一个问题,但是我还没有弄清楚它的实际作用。我习惯于从一个线程向另一个线程屈服的角度考虑yield,但这在这里似乎无关紧要。
该yield关键字实际上这里确实不少。
yield
该函数返回一个实现IEnumerable<object>接口的对象。如果调用函数开始foreach对此对象进行调用,则会再次调用该函数,直到“屈服”为止。这是 C#2.0中 引入的语法糖。在早期版本中,您必须创建自己的对象,IEnumerable然后IEnumerator才能执行此类操作。
IEnumerable<object>
foreach
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不再执行。
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); } } } } }