2017-09-27 5 views
6

Disons que nous avons une interface commecontrainte générique ne tient pas compte de co-variance

public interface IEnumerable<out T> 
{ /*...*/ } 

qui est co-variante dans T.

Ensuite, nous avons une autre interface et une classe mise en œuvre:

public interface ISomeInterface {} 
public class SomeClass : ISomeInterface 
{} 

Maintenant, la co-variance nous permet de faire ce qui suit

IEnumerable<ISomeInterface> e = Enumerable.Empty<SomeClass>(); 

Ainsi, un IEnumerable<SomeClass>est assignable à une variable (ou paramètre de méthode) de type IEnumerable<ISomeInterface>.

Mais si nous essayons cela dans une méthode générique:

public void GenericMethod<T>(IEnumerable<T> p) where T : ISomeInterface 
{ 
    IEnumerable<ISomeInterface> e = p; 
    // or 
    TestMethod(p); 
} 
public void TestMethod(IEnumerable<ISomeInterface> x) {} 

nous obtenons l'erreur compilateur CS0266 nous dire qu'un IEnumerable<T> ne peut pas être converti en un IEnumerable<ISomeInterface>.

La contrainte indique clairement la T est dérivé de ISomeInterface, et depuis IEnumerable<T> est co-variante T, cette mission devrait fonctionner (comme indiqué ci-dessus).

Y at-il une raison technique pour laquelle cela ne fonctionne pas dans une méthode générique? Ou tout ce que j'ai raté rend le compilateur trop cher pour le comprendre?

Répondre

5

Changer votre GenericMethod et ajoutez contrainte générique class:

public void GenericMethod<T>(IEnumerable<T> p) where T : class, ISomeInterface 
{ 
    IEnumerable<ISomeInterface> e = p; 
    // or 
    TestMethod(p); 
} 

Covariance does not support structs, donc nous devons dire que nous voulons utiliser des classes seulement.

+1

Oh, battez-moi à ça. Maintenant, je me souviens avoir lu quelque chose à propos de ce problème de structure/variance il y a quelques jours. Merci pour votre réponse rapide. –

+0

@ RenéVogt heureux d'aider – Backs