の中にIList<> のフラグメントのみを公開するにはどうすればよいでしょうか?質問の回答の 1 つに次のコード スニペットがありました。
IEnumerable<object> FilteredList()
{
foreach(object item in FullList)
{
if(IsItemInPartialList(item))
yield return item;
}
}
yield キーワードはそこで何をするのでしょうか? いくつかの場所で参照されているのを見たことがありますし、別の質問も 1 つありましたが、実際に何をするのかよくわかりません。yield は、あるスレッドが別のスレッドに譲るという意味で考えるのに慣れていますが、ここでは関係ないようです。
ベストアンサー1
コンテキストyield
キーワードは、実際にはここで非常に多くのことを行います。
関数は、インターフェイスを実装するオブジェクトを返しますIEnumerable<object>
。呼び出し関数がforeach
このオブジェクトに対して ing を開始すると、関数は「yield」するまで再度呼び出されます。これは、C# 2.0IEnumerable
で導入された構文糖です。以前のバージョンでは、このようなことを行うには独自のおよびオブジェクトを作成する必要がありました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()
returns であることがわかります1
。2 番目の呼び出しは returns であり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);
}
}
}
}
}