Was ist der beste Weg, um eine IEnumerator auf eine generische IEnumerator zu konvertieren?

StackOverflow https://stackoverflow.com/questions/828342

  •  06-07-2019
  •  | 
  •  

Frage

Ich bin eine benutzerdefinierte Configuration für einen benutzerdefinierten ConfigurationHandler in C # .NET 3.5 schreiben, und ich bin zu wollen, den IEnumerator als generischer IEnumerator belichten.

Was wäre der beste Weg, dies zu erreichen?

Ich bin derzeit mit dem Code:

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();
}

Prost

War es hilfreich?

Lösung

Ich glaube nicht, dass es etwas im Rahmen, aber man konnte man leicht schreiben:

IEnumerator<T> Cast<T>(IEnumerator iterator)
{
    while (iterator.MoveNext())
    {
        yield return (T) iterator.Current;
    }
}

Es ist verlockend, nur Enumerable.Cast<T> von LINQ anrufen und dann GetEnumerator() auf dem Ergebnis nennen - aber wenn Ihre Klasse bereits implementiert IEnumerable<T> und T ist ein Werttyp, der als No-op wirkt, so dass der GetEnumerator() Anruf rekursiv und wirft einen StackOverflowException . Es ist sicher return foo.Cast<T>.GetEnumerator(); zu verwenden, wenn foo ist auf jeden Fall ein andere Objekt (die nicht auf diese eine delegiert zurück), aber sonst sind Sie wahrscheinlich am besten aus den oben stehenden Code verwendet wird.

Andere Tipps

IEnumerable<T> leitet bereits aus IEnumerable so gibt es keine Notwendigkeit, jede Umwandlung zu tun. Sie können einfach auf sie werfen ... naja eigentlich ist es implizit keine Besetzung notwendig.

IEnumerable<T> enumerable = GetGenericFromSomewhere();
IEnumerable sadOldEnumerable = enumerable;
return sadOldEnumerable.GetEnumerator();

Runde in der anderen Richtung ist nicht viel schwieriger, mit LINQ:

var fancyEnumerable = list.OfType<GenericObject>();
return fancyEnumerable.GetEnumerator();

Ich wurde in der gleichen Stack-Überlauf Problem ist, erwähnt laufen einige der Kommentare. In meinem Fall war es aufgrund der Tatsache, dass der GetEnumerator Aufruf der base.GetEnumerator sonst innerhalb Ihrer eigenen GetEnumerator Neudefinition Sie Schleife sein muß.

Dies ist der Code, der die Stack-Überlauf wurde Werfen. Die Verwendung der foreach-Anweisung rufen Sie die gleiche Funktion GetEnumerator Ich versuche, Überlastung:

public new IEnumerator<T> GetEnumerator()
{
    foreach (T type in this)
    {
        yield return type;
    }
}

Ich habe mit einer vereinfachten Version der Original-Post ende als Sie keine Liste Halter verwenden muß.

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;
        }
    }
    ...
}

Sie können OfType<T> und Cast<T> verwenden.

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);

Um einen IEnumerator<T> anstelle eines IEnumerable<T> bekommen Sie nur einen Anruf GetEnumerator()

var enumerator = Digits().OfType<int>().GetEnumerator();

Das funktioniert für mich.

IEnumerator<DataColumn> columnEnumerator = dt.Columns.Cast<DataColumn>().GetEnumerator();
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top