Re: GetEnumerator() vs. GetEnumerable()
コメントしようとしたら長すぎて書けなかったのでここに。
(GetEnumerator() vs. GetEnumerable()のコメントより) siokoshou さん wrote:
まじかんとさん、はじめまして。#Calc、すばらしいですね!サイトにもたびたびお世話になっております。
こちらこそ初めまして。でも私のサイトって何か大したコンテンツありましたっけ?
IEnumerator<>だとforeachで使えません。
ああ、そうでした。foreach 文には IEnumerable も IEnumerator もどっちも使えると勘違いしていました。
それで、元々のGetEnumerable を Google で日本語のページを検索すると、たった数件しかヒットしない。何でだろう?
という話ですが、その2で gushwell さんがIEnumerableを実装する、しないにかかわらず、GetEnumerator()を実装していさえすれば、(中略)と書ける。
と書いてらっしゃるところがポイントのような気がします。
わざわざオブジェクトを IEnumerable に変換する GetEnumerable メソッドを用意しなくても、オブジェクト自身を IEnumerable にしてしまえばいい、というわけです。
また、リストの要素の順を逆にして列挙するというような場合でも、「要素を逆順に列挙する IEnumerator を作る IEnumerable を返すメソッド」よりは「要素を逆順にした新しいリストを返すメソッド」のほうが汎用的なので、結局こういうメソッドの型は IEnumerable そのものではなくて IEnumerable を実装した何か具体的な型ということになります。
実際のところ、yield return を使ったメソッドで戻り値が IEnumerator になっているものは何度か作った経験がありますが、IEnumerable になっているものを作る必要が生じた経験は一度もありませんでした。それで昨日はIEnumerable にするメリットが見出せません
とコメントしたわけですが、その理由は何かというとどうもこういうことのような気がします。つまり、yield return で IEnumerable を返すくらいならいっそ新しいオブジェクトを返したほうがいい、と。まあこれは私のプログラムの設計スタイルの問題かもしれませんが……。
| 固定リンク
コメント
GetEnumerable よりは、GetEnumerator が使われているというのは、納得です。
IEnumerableを実装しなくても、GetEnumeratorを用意すれば、foreachが使えるので、yield return との組み合わせでとても楽に反復子を実装できるからですね。
まじかんとさんは、MyClassに中に、GetRevEnumerable メソッドを作るのではなく、
class MyRevClass {
public MyRevClass(MyClass obj) { ... };
public IEnumerator GetEnumerator() { ... }
}
のように、別クラスを作成することを好むということですか?
これは、設計スタイルの問題なので、なんともいえませんが、MyClassの内部構造を知らないと実装できない可能性があるので、
ケースバイケースかな。
まあ、逆順を求める反復子をつかいたいという要求はそれほどないですがね。
投稿: gushwell | 2007年5月26日 (土) 15時34分
まぁ、別クラスを作るというほどではないにしても、単に「GetEnumerator があるだけの IEnumerable」を返すくらいなら、元のクラスと同じクラスのオブジェクトを返したらどうか、と。
例えば、リストの一部分のみを列挙したい、というとき、「リストの一部分のみを列挙する IEnumerator を返す GetEnumerator メソッドを持つ IEnumerable」を返すメソッドを yield return で作るよりは、「リストの一部分を抜き出した部分リスト」を作って返すメソッドを作ったほうが、列挙以外にもメソッドの使い道が出来てよさそうということです。
(例えば、System.Collections.Geteric.List クラスの GetRange メソッド)
もっとも、要素を逆順にしたリストを作るには要素を逆順に列挙する IEnumerator が必要、などということになったら意味がありませんが。
投稿: まじかんと | 2007年5月26日 (土) 18時07分
> でも私のサイトって何か大したコンテンツありましたっけ?
Java と C# のジェネリクスの違いのページ、大変勉強になりました。あと、ちょくちょくC#関連で検索からたどりついてお世話になっております。ありがとうございます。
> IEnumerable になっているものを作る必要が生じた経験は一度もありませんでした。
LINQ to ObjectがIEnumerableを関数型言語で言うところの遅延リストに見立てて、データをやりとりする共通の口として使っています。なので、きっとこれからはIEnumerableを扱う機会が増えていくと思います。
LINQに逆順にする汎用のイテレータReverseがあったりします。
投稿: siokoshou | 2007年5月27日 (日) 06時33分
> 「リストの一部分を抜き出した部分リスト」を作って返すメソッドを作ったほうが、列挙以外にもメソッドの使い道が出来てよさそうということです。
これ、まさにLINQです!
投稿: siokoshou | 2007年5月27日 (日) 06時37分
LINQ かぁ……。
C# 3.0 のことはほとんど何も知らないんですよねぇ。興味がないわけではないんですがいかんせん時間が無くて。
投稿: まじかんと | 2007年5月27日 (日) 11時54分
↓の記事なんかいかがでしょうか。LINQ全般を学べるわけではないですが、C#1.1→LINQへとコードを徐々に書き換えていってみせる入門記事です。文章読まなくてもコードの変化を見るだけでおもしろいです。私のお気に入り記事です。
http://blogs.msdn.com/jomo_fisher/archive/2005/09/13/evolution-of-a-c-query-step-by-step-from-c-1-1-to-linq.aspx
投稿: siokoshou | 2007年5月27日 (日) 16時47分
紹介してくださった記事を読みました。
何だか、C# が言語としてどんどん高級化してゆく様が見て取れるような気がします。C# 3.0 もなかなか面白い言語になりそうですね。(この調子でいくと C# 5.0 辺りで機能を詰め込みすぎて破綻するんじゃないかという一抹の不安もありますが)
投稿: まじかんと | 2007年5月28日 (月) 23時15分
> 破綻するんじゃないかという一抹の不安もありますが
同感です(^^;
投稿: siokoshou | 2007年5月29日 (火) 14時11分