質問

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が値型である場合、no-opとして機能するため、 StackOverflowException呼び出しは再帰し、return foo.Cast<T>.GetEnumerator();をスローします。 foo different オブジェクト(これに委任されない)である場合は<=>を使用しても安全ですが、それ以外の場合は、上記のコードを使用するのが最善です。

他のヒント

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();
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top