Question concernant IEnumerable et IEnumerator
-
13-10-2019 - |
Question
J'utilise le code suivant pour permettre myClass d'utiliser foreach. Mais je suis assez nouveau à la programmation et avoir une certaine difficulté à comprendre le code suivant. J'ai décrit mes problèmes dans les commentaires. Je vous serais reconnaissant de fournir des informations.
public class MyClass : IEnumerable<string>
{
//1) What is IEnumerator for?
// Whats the difference between IEnumerator and IEnumerable
public IEnumerator<string> GetEnumerator()
{
yield return "first";
yield return "second";
}
//2) What is it for? It just calls above method
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
//3) Lastly what benefits I have from implementing genetic interface
//IEnumerable<string> instead of just IEnumerable
La solution
Quelle est la différence entre IEnumerator et IEnumerable?
La réponse de Jason est bonne, mais je pensais que je venais d'ajouter que je pense à ce sujet. Imaginez que vous avez une séquence:
1, 1, 2, 3, 5, 8, 13, ...
Maintenant, imaginez que vous avez une flèche pointant à une position de cette séquence:
1, 1, 2, 3, 5, 8, 13, ...
^
« une flèche » est un objet qui peut faire deux choses. Tout d'abord, il peut vous donner la chose qu'il pointe du doigt. En second lieu, il peut se faire pointer sur la chose suivante.
IEnumerator est une flèche. Il a une propriété, actuelle, qui vous donne la chose qu'il pointe du doigt. Il a une méthode, MoveNext () qui se fait pointer sur la chose suivante.
Comment obtenez-vous une flèche en premier lieu? Vous avez besoin d'une usine de flèche. Vous demandez à l'usine pour une flèche, et il vous donne une flèche qui pointe vers le premier élément de la séquence.
IEnumerable est une usine de flèche. Il a une méthode, GetEnumerator, qui vous donne une flèche au premier élément de la séquence.
Une belle propriété de ce système est que vous pouvez avoir plusieurs flèches pointant vers des endroits différents dans la même séquence.
quels sont les avantages de la mise en œuvre interface générique IEnumerable au lieu de simplement IEnumerable?
Supposons que la séquence est d'entiers. Si vous implémentez IEnumerable
alors quand vous dites
foreach(int x in mysequence)
ce qui va réellement faire est de convertir l'int dans la séquence à l'objet, la boxe l'entier, puis immédiatement Unbox le dos d'objet entier, en ajoutant une allocation de mémoire complètement inutile à chaque opération. Si le compilateur sait que la séquence est d'entiers alors il peut sauter l'opération de boxe inutile.
Supposons que la séquence est de chaînes. Si vous implémentez IEnumerable<string>
alors vous pouvez dire:
string first = mysequence.First();
Si vous n'êtes pas, alors vous avez à dire
string first = (string)mysequence.First();
qui est inutile et source d'erreurs. Plutôt que de demander au compilateur via un casting que le type est une chaîne, vous pouvez simplement garantie que le type est une chaîne en utilisant le système de type.
Autres conseils
1) Qu'est-ce que
IEnumerator
pour? Quelle est la différence entreIEnumerator
etIEnumerable
?
IEnumerator
est une interface qui représente les méthodes que vous énumérons une séquence. La différence entre IEnumerator
et IEnumerable
est que le premier représente le contrat pour les objets que vous énumérons une séquence, et celle-ci représente le contrat pour les objets qui sont une séquence qui peuvent être dénombrés sur.
public IEnumerator<string> GetEnumerator() {
yield return "first";
yield return "second";
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
2) Quel est-il? Il appelle la méthode juste au-dessus.
L'ancien représente une mise en œuvre de la méthode GetEnumerator
sur le contrat IEnumerable<string>
. Ce dernier représente une mise en œuvre explicite de la méthode GetEnumerator
sur le contrat IEnumerable
. Le problème est que les deux contrats ont une méthode nommée GetEnumerator
mais avec différents types de retour de sorte qu'une méthode ne peut pas satisfaire simultanément les deux contrats (toute IEnumerable<T>
mise en œuvre de classe doit également mettre en œuvre IEnumerable
comme IEnumerable<T> : IEnumerable
). Ce dernier appelle la mise en œuvre de IEnumerable<string>.GetEnumerator
comme c'est une mise en œuvre sensible qui renvoie un IEnumerator
comme IEnumerator<string> : IEnumerator
.
3) Enfin les avantages que je
IEnumerable<string>
de la mise en œuvre d'interface générique au lieu de simplementIEnumerable
?
Le typage fort. Vous savez que les éléments d'une IEnumerable<string>
de séquence sont toutes les instances de String
alors que vous ne savez pas que pour IEnumerable
et pourrait finir par essayer de jeter un élément de celui-ci à une instance de String
quand il ne peut pas être.
Ceci est la déclaration de IEnumerable<T>
:
public interface IEnumerable<out T> : IEnumerable
{
IEnumerator<T> GetEnumerator();
}
Vous avez pas le choix, vous Vous pour implémenter l'interface IEnumerable non générique ainsi. Vous obtiendrez une erreur de compilation si vous omettez la mise en œuvre IEnumerable.GetEnumerator (). C'est des bagages laissés par les jours 1.x .NET où les génériques ne sont pas encore disponible et la période de transition pour .NET 2.0 où il avait besoin pour soutenir Interop avec des assemblages .NET 1.x. Nous sommes coincés avec.
1) Qu'est-ce IEnumerator pour?
IEnumerator est la partie réelle de travail avec le MoveNext () et les membres actuels.
Quelle est la différence entre IEnumerator et IEnumerable
IEnumerable est l'interface pour une collection de signaux qu'elle a un GetEnumerator ().
2) [GetEnumerator non-générique] Qu'est-ce pour? Il appelle juste au-dessus méthode
La méthode non-générique est juste là pour la compatibilité descendante. Notez qu'il est déplacé « hors de vue », autant que possible par l'utilisation de la mise en œuvre explicite. Mettre en œuvre parce que vous devez puis oublier.
3) Enfin les avantages que je de mettre en œuvre l'interface génétique IEnumerable au lieu de simplement IEnumerable
Lorsqu'il est utilisé avec le foreach
adavantage est petite, comme foreach tapera la variable moulé en boucle. Il vous permettra d'utiliser var
dans le foreach:
foreach (var s in myClassInstance) // needs `IEnumerable<string>`
foreach (string s in myClassInstance) // works with `IEnumerable` as well
Mais avec IEnumerable<string>
vous avez également une interface de type sécurisé à d'autres domaines, notamment LINQ:
MyClass mc = new MyClass ();
string s = mc.FirstOrDefault();
GetEnumerator
a été autour depuis avant les médicaments génériques ont été introduits dans la langue, afin de ne pas casser le code pré-existant, les appels de méthode par défaut par le biais de la mise en œuvre générique.
Avec une énumération générique, le consommateur de votre classe n'a pas besoin de jeter chaque élément à chaîne lorsque itérer.
En ce qui concerne la question 3, voici quelques réponses (pourquoi les génériques d'utilisation?):
Doit-on utiliser Collection générique pour améliorer la sécurité et performance?
En bref, utiliser les collections génériques à chaque fois que vous le pouvez.