2017-08-15 12 views
-1

Je fais la collecte, la mise en œuvre IEnumerable explicitement et en essayant de itérer de l'intérieur:Attention - ne met pas en œuvre le modèle de « collection »

public class MyCollection<T> : IEnumerable<T>, IEnumerable 
{ 
    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 
    IEnumerator<T> IEnumerable<T>.GetEnumerator() => GetEnumerator(); 
    IEnumerator<T> GetEnumerator() { yield return default(T); } // test 

    public void Test() 
    { 
     foreach (var item in this) { } // here is warning 
    } 
} 

Je reçois avertissement du compilateur à this:

Avertissement CS0279 'MyCollection' n'implémente pas le modèle 'collection'. 'MyCollection.GetEnumerator()' est statique ou non publique.

Enfer oui, ce n'est pas public. Pourquoi ça devrait être? Je peut le rendre public, mais il est pas nécessaire pour foreach extérieur de type:

foreach (var item in new MyCollection<string>()) { } // no warning 

Est-ce que je fais quelque chose de mal?

+0

simplement appeler autre chose? 'GetEnumeratorImpl'? Ou n'utilisez simplement pas l'implémentation d'interface explicite pour 'IEnumerable .GetEnumerator?' –

+0

@JonSkeet, donc c'est seulement un compilateur de noms? – Sinatr

+0

Oui - parce que la correspondance de modèle dans 'foreach' * trouve * la méthode' GetEnumerator() ', mais ne peut pas l'utiliser. Ajout d'une réponse maintenant ... –

Répondre

4

L'avertissement existe parce que le compilateur C# peut gérer foreach dans un certain nombre de façons différentes. Un de ces moyens est de trouver une méthode GetEnumerator avec un type de retour approprié. Cela est vérifié avant le compilateur vérifie si le type de l'expression implémente IEnumerable ou IEnumerable<T>.

Dans votre cas, cela revient à trouver la méthode GetEnumerator sans paramètre, mais ce n'est pas public. La spécification C# recommande un avertissement à ce stade, car vous pouvez avoir prévu pour être utilisable pour foreach. De la spécification C# 5, section 8.8.4, Souligné par l'auteur:

  • Effectuer la résolution de surcharge à l'aide du groupe de la méthode résultante et une liste d'arguments vide. Si la résolution de surcharge n'aboutit à aucune méthode applicable, entraîne une ambiguïté ou aboutit à une méthode unique, mais que cette méthode soit statique ou non publique, vérifiez l'existence d'une interface énumérable, comme décrit ci-dessous. Il est recommandé d'émettre un avertissement si la résolution de surcharge produit autre chose qu'une méthode d'instance publique non ambiguë ou aucune méthode applicable.

Tous les éléments suivants résoudrait le problème:

  • Renommer GetEnumerator-GetEnumeratorImpl ou similaire:

    IEnumerator IEnumerable.GetEnumerator() => GetEnumeratorImpl(); 
    IEnumerator<T> IEnumerable<T>.GetEnumerator() => GetEnumeratorImpl(); 
    IEnumerator<T> GetEnumeratorImpl() { yield return default(T); } 
    
  • Ne pas utiliser l'implémentation d'interface explicite pour IEnumerable<T>.GetEnumerator() - mettre la mise en œuvre là

    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 
    public IEnumerator<T> GetEnumerator() => { yield return default(T); } 
    
  • Mettre la mise en œuvre IEnumerable<T>.GetEnumerator, mais jeté this à IEnumerable<T> en IEnumerable.GetEnumerator pour l'appeler:

    IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<T>) this).GetEnumerator(); 
    IEnumerator<T> IEnumerable<T>.GetEnumerator() => { yield return default(T); } 
    
+0

La deuxième option est la plus propre je pense. Mon erreur évidente consistait à implémenter explicitement les deux interfaces, seulement une doit être. Merci. – Sinatr

2

Voir l'explication de CS0279 d'avertissement du compilateur ici: https://msdn.microsoft.com/en-us/library/bz2286x8(v=vs.90).aspx

Il y a plusieurs déclarations en C# qui reposent sur des motifs définis, tels que foreach et l'utilisation. Par exemple, foreach repose sur la classe de collecte implémentant le modèle énumérable. Cette erreur se produit lorsque le compilateur est incapable de faire la correspondance en raison d'une méthode déclarée statique ou non publique. Les méthodes dans les modèles doivent être des instances des classes et être publiques.

(Souligné par l'auteur)

+0

Pas le point. Lisez à propos de l'implémentation de l'interface [explicite] (https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/explicit-interface-implementation). External 'foreach' n'a besoin d'aucune méthode explicite pour être public. En fait vous ** ne pouvez pas ** rendre l'implémentation explicite publique – Sinatr