R.Tanaka.Ichiro's Blog

主にC# な話題です

目次

Blog 利用状況

ニュース

イテレータの後始末

http://blogs.wankuma.com/rti/archive/2008/02/12/122771.aspx
クエリー式とイテレータ

これの続きっちゃー続きなんですが、テーマはちょっと違うのでタイトルは別にしました。
先日のデブサミで、通りすがりの NyaRuRu さんと上記のエントリーに関する話をしていた時に、教えてもらった

イテレータの後始末

の話です。

まず、イテレータの動きです。以下のコードと、その動きを見れば明らかです。


public void Test() {
  foreach(var x in Range(0, 3)) Console.WriteLine(x);
}
public IEnumerable<int> Range(int start, int count) {
  Console.WriteLine("素敵だし爽やかRさん");
  for(var i = start; i < start + count; ++i) yield return i;
  Console.WriteLine("わんくま同盟の若きホープ");
}



【実行結果】

素敵だし爽やかRさん
0
1
2
わんくま同盟の若きホープ


つまり yield で一旦呼び出し側に制御を返した後に再度呼ばれたら、その続きから実行するという動きをします。
じゃあ、以下のように中断したらどうなるでしょう?


public void Test() {
  foreach(var x in Range(0, 3)) {
    Console.WriteLine(x);
    return;
  }
}



【実行結果】

素敵だし爽やかRさん
0


つまり、Rさんが「素敵だし爽やか」であることはわかりますが「わんくま同盟の若きホープ」であることまではわかりません。大問題です!
他にも Range メソッド内でアンマネージリソースを使っている場合の解放に関しても、少しだけ問題が生じます。

解決策として思い浮かぶのは、try - finally です。


static public IEnumerable<int> Range(int start, int count) {
  try {
    Console.WriteLine("素敵だし爽やかRさん");
    for(var i = start; i < start + count; ++i) yield return i;
  }
  finally {
    Console.WriteLine("わんくま同盟の若きホープ");
  }
}


【実行結果】

素敵だし爽やかRさん
0
わんくま同盟の若きホープ


今度は、Rさんが「素敵だし爽やか」で「わんくま同盟の若きホープ」であることがわかります。
try - finally の技は、using ステートメントが登場するまでは当然のように使われていましたが、イテレーターブロックでも正しく動作するというのは、さすが C# というところでしょうか。

投稿日時 : 2008年2月18日 11:37

Feedback

# re: イテレータの後始末 2008/02/18 21:51 NyaRuRu

LINQ のような IEnumerator 連鎖では,列挙の中断を外部へ分離しても,列挙の終了を検知して終了処理を行うことができます.
この結果,for ループのように「繰り返し」と「中断判定」を一度に行う必要はもはや無くなりました.
上の例であれば,要素を取り出すごとにインクリメントするイテレータから,Take(count) で必要な個数取り出すというコードに書き換えられる,というわけですね.
「(無限の)繰り返し」と,「中断判定」を分けておくことで,後から組み替えがやりやすくなるというメリットがあります.

イテレータが finally を考慮することは,この分離を安全に行うために無くてはならなかったものです.
C# 2.0 の段階で C# 3.0 に向けて打たれていた布石と言えるでしょう.
以下参考までに.

http://d.hatena.ne.jp/NyaRuRu/20070331/p1
http://d.hatena.ne.jp/NyaRuRu/20060315/p1
http://www.atmarkit.co.jp/fdotnet/special/cs20review02/cs20review02_04.html

# re: イテレータの後始末 2008/02/18 22:02 NyaRuRu

もう一点,C++/CLI の STL/CLR を私がどうしても好きになれない理由が,まさにここに関係しています.
STL/CLR の collection_adapter を使うと,Dispose が呼ばれず宙ぶらりんになっちゃうんですよね.
http://d.hatena.ne.jp/NyaRuRu/20070803/p1

# re: イテレータの後始末 2008/02/19 18:45 R・田中一郎

リンク先見ましたよ。
おかげさまで、凄くわかりやすかったです。

# イテレータの後始末(その2) 2008/02/20 11:11 R.Tanaka.Ichiro's Blog

イテレータの後始末(その2)

# イテレータの後始末(その2) 2008/02/20 11:13 R.Tanaka.Ichiro's Blog

イテレータの後始末(その2)

# re: イテレータの後始末(その2) 2008/02/21 15:13 R.Tanaka.Ichiro's Blog

re: イテレータの後始末(その2)

# re: ????????? 2021/08/08 7:49 hcqs 400

hloroquine https://chloroquineorigin.com/# do you need a prescription for hydroxychloroquine

タイトル
名前
Url
コメント