C#.NET 3.5でカスタムConfigurationHandlerのカスタムConfigurationElementCollectionを作成していて、IEnumeratorを汎用IEnumeratorとして公開したいと考えています。
これを達成するための最良の方法は何でしょうか?
私は現在コードを使用しています:
public new IEnumerator <GenericObject> GetEnumerator() { var list = new List(); var baseEnum = base.GetEnumerator(); while(baseEnum.MoveNext()) { var obj = baseEnum.Current as GenericObject; if(obj!= null) list.Add (obj); } return list.GetEnumerator(); }
乾杯
フレームワークには何もないと思いますが、簡単に書くことができます。
_IEnumerator<T> Cast<T>(IEnumerator iterator)
{
while (iterator.MoveNext())
{
yield return (T) iterator.Current;
}
}
_
LINQから_Enumerable.Cast<T>
_を呼び出してから、結果に対してGetEnumerator()
を呼び出すのは魅力的ですが、クラスがすでに_IEnumerable<T>
_を実装していて、T
が値型である場合、ノーオペレーションとして機能するため、GetEnumerator()
呼び出しは再帰し、StackOverflowException
をスローします。 foo
が間違いなく異なるオブジェクト(これはこのオブジェクトに委任されない)である場合はreturn foo.Cast<T>.GetEnumerator();
を使用しても安全ですが、それ以外の場合はおそらく最善です。上記のコードを使用します。
IEnumerable<T>
はすでにIEnumerable
から派生しているため、変換を行う必要はありません。単純にキャストすることができます...実際には、キャストは必要ありません。
IEnumerable<T> enumerable = GetGenericFromSomewhere();
IEnumerable sadOldEnumerable = enumerable;
return sadOldEnumerable.GetEnumerator();
LINQを使用すると、逆の方向に進むことはそれほど難しくありません。
var fancyEnumerable = list.OfType<GenericObject>();
return fancyEnumerable.GetEnumerator();
私は、コメントのいくつかが言及されているのと同じスタックオーバーフローの問題に遭遇していました。私の場合、GetEnumerator呼び出しをbase.GetEnumeratorに対して行う必要があるという事実が原因でした。そうしないと、独自のGetEnumerator再定義内でループします。
これは、スタックオーバーフローをスローしていたコードです。 foreachステートメントを使用すると、オーバーロードしようとしているのと同じGetEnumerator関数が呼び出されます。
public new IEnumerator<T> GetEnumerator()
{
foreach (T type in this)
{
yield return type;
}
}
リストホルダーを使用する必要がないため、元の投稿の簡略版になりました。
public class ElementCollection<T> : ConfigurationElementCollection, IList<T>
...
public new IEnumerator<T> GetEnumerator()
{
var baseEnum = base.GetEnumerator();
while (baseEnum.MoveNext())
{
yield return baseEnum.Current as T;
}
}
...
}
_OfType<T>
_および_Cast<T>
_を使用できます。
_public static IEnumerable Digits()
{
return new[]{1, 15, 68, 1235, 12390, 1239};
}
var enumerable = Digits().OfType<int>();
foreach (var item in enumerable)
// var is here an int. Without the OfType<int(), it would be an object
Console.WriteLine(i);
_
_IEnumerator<T>
_の代わりに_IEnumerable<T>
_を取得するには、GetEnumerator()
を呼び出すだけです。
_var enumerator = Digits().OfType<int>().GetEnumerator();
_
これは私にとってはうまくいきます。
IEnumerator<DataColumn> columnEnumerator = dt.Columns.Cast<DataColumn>().GetEnumerator();