2010-12-10 86 views
6

Lorsque j'implémente IList<T>, je trouve que je dois définir deux méthodesGetEnumerator. L'un renvoie une valeur de type IEnumerator, tandis que l'autre renvoie IEnumerator<T>.Pourquoi l'implémentation de 'IList <T>' nécessite-t-elle la définition de deux méthodes 'GetEnumerator'?

Je suis un peu confus au sujet de la différence entre ces deux méthodes GetEnumerator. Alors que les types de retour sont évidemment différents, ne contiennent-ils pas essentiellement les mêmes données?

En outre, pourquoi les deux versions de GetEnumerator peuvent-elles exister en tant que méthodes lorsqu'elles ne diffèrent que par le type de retour? Cela semble violer la règle en C# qui spécifie que les méthodes surchargées ne peuvent pas différer uniquement par type de retour.

Répondre

8

Les deux devraient retourner les mêmes données, oui.

IEnumerator provient de .Net v1.1, avant l'introduction du typage générique. IEnumerator<T> est la version générique ajoutée dans .Net v2.

La "ancienne" version, IEnumerator, a été conservée pour des raisons de compatibilité, donc maintenant IList<T> implémente les deux.

La différence entre les deux est que le IEnumerator non générique renvoie l'objet tandis que le générique IEnumerator<T> renvoie T. Bien que le compilateur C# insérera une distribution pour que le IEnumeratornon-générique semble fortement typé lorsqu'il est utilisé dans une foreach.

La présence d'un argument de type générique est suffisante pour que le compilateur puisse différencier les deux interfaces, mais pour qu'une classe puisse implémenter les deux, il faut qu'elle soit explicitement implémentée.

+1

Pas tout à fait vrai, l'argument générique n'est pas suffisant - l'un est implémenté explicitement, l'autre ne l'est pas. –

+1

J'appellerais à peine l'utilisation non générique de IEnumerator dans une magie de boucle foreach. Il tente simplement une conversion de l'objet au type que vous spécifiez. Si cela échoue, vous obtiendrez une exception. –

+0

Accepté pour expliquer le problème de compatibilité descendante. Merci. – MyNameIsJob

7

Les deux proviennent d'interfaces distinctes qui IList elle-même implémente, qui est pourquoi vous devez mettre en œuvre à la fois:

public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable 

Et ils sont tous deux capables d'exister en raison de Explicit Interface Implementation.

+0

Merci pour ce lien. Cela a aidé plus que tout. – MyNameIsJob

3

Oui, les deux méthodes doivent renvoyer les mêmes données. Ils peuvent coexister car ils font partie de deux interfaces différentes, IEnumerable et IEnumerable<T>.

0

IList<T> Implémente à la fois IEnumerable<T> et IEnumerable. Les différentes implémentations de GetEnumerator proviennent de chacune de ces interfaces. Les deux devraient retourner les mêmes données.

1

Ils ont tous deux peuvent exister parce que l'un d'entre eux sera mis en œuvre explicitly:

IEnumerator IEnumerable.GetEnumerator() 
{ 

} 

Si vous essayez de les rendre à la fois implicitement défini, vous obtenez des erreurs de compilation.

Oui, ils doivent tous deux renvoyer les mêmes données.

Vous devez définir les deux versions de GetEnumerator afin de satisfaire les deux interfaces (IEnumerable et IEnumerable<T>) à partir de laquelle IList<T> est dérivé. En pratique, cependant, vous avez tendance à trouver la version non générique de GetEnumerator qui appelle simplement la version générique dans la plupart des implémentations.

0

IEnumerator objets énumère, alors que IEnumerator T. Pour énumère la deuxième question, la deuxième fonction est qualifié:

System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 

    } 

vs

public IEnumerator<T> GetEnumerator() 
    { 

    }