Quel est le meilleur moyen de convertir un IEnumerator en un IEnumerator générique?

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

  •  06-07-2019
  •  | 
  •  

Question

J'écris un ConfigurationElementCollection personnalisé pour un ConfigurationHandler personnalisé dans C # .NET 3.5 et je souhaite exposer l'IEnumerator en tant que IEnumerator générique.

Quel serait le meilleur moyen d'y parvenir?

J'utilise actuellement le 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();
}

A bientôt

Était-ce utile?

La solution

Je ne crois pas qu'il y ait quoi que ce soit dans le cadre, mais vous pouvez facilement en écrire un:

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

Il est tentant d'appeler simplement Enumerable.Cast<T> depuis LINQ, puis d'appeler GetEnumerator() le résultat - mais si votre classe implémente déjà IEnumerable<T> et que T est un type de valeur, il agit comme un non-op, alors l’appel StackOverflowException revient et lance un return foo.Cast<T>.GetEnumerator();. Vous pouvez utiliser foo lorsque <=> est vraiment un objet différent (qui ne délègue pas à celui-ci), mais sinon, vous feriez probablement mieux d'utiliser le code ci-dessus.

Autres conseils

IEnumerable<T> provient déjà de IEnumerable, il n’est donc pas nécessaire d’effectuer une conversion. Vous pouvez simplement y lancer ... eh bien, en réalité, cela n’implique implicitement aucun casting.

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

Inverser l’inverse n’est pas beaucoup plus difficile avec LINQ:

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

Je rencontrais le même problème de débordement de pile que certains commentaires. Dans mon cas, cela était dû au fait que l'appel GetEnumerator devait être envoyé à la base.GetEnumerator, sinon vous passez en boucle dans votre propre redéfinition de GetEnumerator.

C'est le code qui provoquait le débordement de pile. L'utilisation de l'instruction foreach appelle la même fonction GetEnumerator que j'essaie de surcharger:

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

Je me suis retrouvé avec une version simplifiée du message d'origine, car vous n'avez pas besoin d'utiliser un détenteur de liste.

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

Vous pouvez utiliser OfType<T> et 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);

Pour obtenir un IEnumerator<T> au lieu d'un IEnumerable<T>, vous pouvez simplement appeler GetEnumerator()

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

Cela fonctionne pour moi.

IEnumerator<DataColumn> columnEnumerator = dt.Columns.Cast<DataColumn>().GetEnumerator();
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top