なクラスを実装する必要があるとIEnumerable利用Foreach
-
02-07-2019 - |
質問
このスレッドセーフで、C#、私のクラスを私が使用していることから、他のDLL.は実装しませんIEnumerableが2つの方法を返IEnumerator.があるので、使用できますforeachで商品情報を順次取得することができます。のクラスを使用していで密封されています。
解決
foreach
は ない 必要と IEnumerable
, とは逆に、人気の"信念"である。すべてを必要とする方法 GetEnumerator
返すのanyオブジェクトの方法 MoveNext
の取得-財産 Current
適切なフェースの通称です。
/編集:この点、質問の場合で言えば、しいてのデモインのホテルを表示.できtriviallyあなたを包み込むオブジェクト、しかし、enumerable:
class EnumerableWrapper {
private readonly TheObjectType obj;
public EnumerableWrapper(TheObjectType obj) {
this.obj = obj;
}
public IEnumerator<YourType> GetEnumerator() {
return obj.TheMethodReturningTheIEnumerator();
}
}
// Called like this:
foreach (var xyz in new EnumerableWrapper(yourObj))
…;
/編集:以下の方法により提案された複数の人が ない る場合、方法を返します。 IEnumerator
:
foreach (var yz in yourObj.MethodA())
…;
他のヒント
Re:場合はforeachを必要としません、明示的なインターフェース規約は、すべGetEnumeratorを反映?
していったんでコメント来ないが評判です。)
いると示唆 ランタイム 反射します。ではでcompiletimeも知られていない事実であることを確認して下さい場合、返されるオブジェクト が 実施IEnumeratorはディスポ品です。
この行動を考えます(runnable)のスニペット.
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication3
{
class FakeIterator
{
int _count;
public FakeIterator(int count)
{
_count = count;
}
public string Current { get { return "Hello World!"; } }
public bool MoveNext()
{
if(_count-- > 0)
return true;
return false;
}
}
class FakeCollection
{
public FakeIterator GetEnumerator() { return new FakeIterator(3); }
}
class Program
{
static void Main(string[] args)
{
foreach (string value in new FakeCollection())
Console.WriteLine(value);
}
}
}
による MSDN:
foreach (type identifier in expression) statement
が表現は:
オブジェクトの収集または配列表現です。は、コレクションの型の要素 必換の識別子 タイプです。ティ設定は行わないでください。表現 評価はnullになります。評価タイプ を実装したIEnumerableまたはタイプ ることを宣言しGetEnumerator方法です。後者の場合、GetEnumerator べきかを返しタイプ 具IEnumeratorたことを宣言し全ての に定義されている方法IEnumerator.
答え:
必要なものは、シェイクスピアの"マクベス"という名前のメソッド GetEnumerator, を返すIEnumeratorしております。これを達成プラッパー:
class ForeachWrapper
{
private IEnumerator _enumerator;
public ForeachWrapper(Func<IEnumerator> enumerator)
{
_enumerator = enumerator;
}
public IEnumerator GetEnumerator()
{
return _enumerator();
}
}
使用量:
foreach (var element in new ForeachWrapper(x => myClass.MyEnumerator()))
{
...
}
から C#言語仕様:
のコンパイル時の処理の foreach文の最初の決定を 回収型の列挙子型 要素タイプの異なるアイコンで表示されます。この 決定として進められている。
場合にはXの発現が配列型であるそれは暗黙的な 参照変換Xからの システム。ョンにします。IEnumerable インターフェイス(年。配列 このインタフェースを実装した).の コレクション型の システム。ョンにします。IEnumerable インタフェースの列挙子タイプの システム。ョンにします。IEnumerator インターフェースおよび要素の型が、 要素型の配列タイプX
その他のいかどうか判定の型のXについては適切な GetEnumerator方法
を行う会員のルックアップのタイプX識別子GetEnumeratorない 型引数になります。た場合には、速やかにこれを会員のルックアップ が発生しない試合なのか、 生曖昧性、生 一致しない方法をグループ チェックするenumerable大規模シミュレーションを行い、 以下に示す。おすすめです この警告を発行する会員が退会した場合、会員の ルックアップの生産ものを除く 法グループではない。
を行う過負荷解像を組み合わせた低解像度による方法することが重要であると 空の引数リスト。過負荷の場合 決議の結果は該当しない 方法、結果は曖昧になり得ますし、又は 結果は単な方法が このメソッドは静的な 公認enumerable 大規模シミュレーションを行い、以下に示す。であ ることを推奨警告を発行する が過負荷分解能生 何もしないで明白な公共 インスタンスメソッドまたは該当しない ます。
場合、戻り値の型マッサージサービスのGetEnumeratorメソッドはクラス 構造体やインタフェースの種類、エラーが 生産され、それ以上のステップ ます。
会員のルックアップを行い、Eの識別子電流とな 型引数になります。た場合には、速やかにこれを会員のルックアップ が発生しない試合の結果は エラー、またはその結果をも 以外の公共のインスタンス性 許可読み、エラーが発生する せ、更なる措置がとられます。
会員のルックアップを行い、Eの識別子MoveNextない 型引数になります。た場合には、速やかにこれを会員のルックアップ が発生しない試合の結果は エラー、またはその結果をも 以外の方法をグループは、エラーが 生産され、それ以上のステップ ます。
過負荷分解能について興味があるという方法をグループ空 引数の一覧です。が過負荷分解能 結果は該当しない方法 結果は曖昧さや結果 単一の方法その方法 は静的な、またはその 戻り値の型がbool、エラーが 生産され、それ以上のステップ ます。
は、コレクション型がXの列挙子タイプEの要素 型は、現在の 物件です。
その他、チェックするenumerableインターフェース:
がある場合は同一型キャッシュ-フローのバランスが暗黙的な 変換からのXインタフェースの システム。ョンにします。クラスを提供します。.IEnumerable<T>, そのコレクション型であるこ インタフェースの列挙子タイプの インタ システム。ョンにします。クラスを提供します。.IEnumerator<T>, の要素の型がT.
それ以外の場合で、以上のようなシリコーンコーティング処理を、エラーが 生産され、それ以上のステップ ます。
それ以外の場合で、暗黙的に変換Xからの システム。ョンにします。IEnumerable インタフェースの収集タイプ このインタフェースの型の列挙子 面 システム。ョンにします。IEnumerator、 要素の型はオブジェクトです。
それ以外の場合、エラーが発生すると、更なる措置がとられます。
ない厳重に管理いたします。どのクラスは、必要なGetEnumerator,MoveNext、リセット、および現在の会員ですforeach
りません、必要な時に必要なだけ、GetEnumeratorの方法、例えば:
class Counter
{
public IEnumerable<int> Count(int max)
{
int i = 0;
while (i <= max)
{
yield return i;
i++;
}
yield break;
}
}
と呼ばれるこの方法:
Counter cnt = new Counter();
foreach (var i in cnt.Count(6))
{
Console.WriteLine(i);
}
きずなどで包んで、ちなみにする"foreachable"だんだんと減っていくという手法"GetEnumerator"の署名を表します。
class EnumerableAdapter
{
ExternalSillyClass _target;
public EnumerableAdapter(ExternalSillyClass target)
{
_target = target;
}
public IEnumerable GetEnumerator(){ return _target.SomeMethodThatGivesAnEnumerator(); }
}
指定されたクラスのX方法A、Bの両方に戻IEnumerableすが、foreachのクラスのようになります:
foreach (object y in X.A())
{
//...
}
// or
foreach (object y in X.B())
{
//...
}
その意味にenumerablesによって返されるBは定義されています。
@Brian:いうループの値を返しからメソッドの呼び出しまたはクラス自体 ばんは、クラスによるものがな配列を利用できるとforeach.
アクセスを可foeachすべての必要がないメソッドは、publicメソッドを返すとIEnumerator名GetEnumerator()すると、その:
以下のクラスされているとは思いませんが、実はIEnumerable IEnumerator:
public class Foo
{
private int[] _someInts = { 1, 2, 3, 4, 5, 6 };
public IEnumerator GetEnumerator()
{
foreach (var item in _someInts)
{
yield return item;
}
}
}
また、GetEnumerator()メソッドが書き込まれる:
public IEnumerator GetEnumerator()
{
return _someInts.GetEnumerator();
}
用途-使用方法についてはforeach(このラッパーを使い、クラスのインスタンス):
foreach (int item in new Foo())
{
Console.Write("{0,2}",item);
}
版画
1 2 3 4 5 6
のタイプのみを必要として公開/非静的/非dev/parameterlessという名前のメソッド GetEnumerator
を返しますもの公開 MoveNext
方法および公 Current
物件です。として憶Mrエリック-Lippertどこか この設計とともに、収前の一般時代とともに、それらの安全性およびボクシングに関する課題の場合の値です。
例えばこの作品:
class Test
{
public SomethingEnumerator GetEnumerator()
{
}
}
class SomethingEnumerator
{
public Something Current //could return anything
{
get { }
}
public bool MoveNext()
{
}
}
//now you can call
foreach (Something thing in new Test()) //type safe
{
}
これによってコンパイラ:
var enumerator = new Test().GetEnumerator();
try {
Something element; //pre C# 5
while (enumerator.MoveNext()) {
Something element; //post C# 5
element = (Something)enumerator.Current; //the cast!
statement;
}
}
finally {
IDisposable disposable = enumerator as System.IDisposable;
if (disposable != null) disposable.Dispose();
}
何かに注目すべきは、調査員が優先関係では以下のようになりました場合 public GetEnumerator
方法、それはデフォルトの選択 foreach
誰を実施します。例えば:
class Test : IEnumerable<int>
{
public SomethingEnumerator GetEnumerator()
{
//this one is called
}
IEnumerator<int> IEnumerable<int>.GetEnumerator()
{
}
}
(かない場合には公開を実施(ieのみ明示的に実施し、優先順位は以下のようになりま IEnumerator<T>
> IEnumerator
.)