2009-02-15 7 views
2

Pourquoi cela ne fonctionne-t-il pas?Implémentation générique de l'interface

public interface IPoint 
{ 
    // not important 
} 

public interface IPointList 
{ 
    List<IPoint> Points { get; } 
} 

public abstract class Point : IPoint 
{ 
    // implemented IPoint 
} 

public abstract class PointList<TPointType> : IPointList 
    where TPointType: IPoint 
{ 
    public abstract List<TPointType> Points { get; } // <- doesn't compile 
} 

Le TPointType doit évidemment être un IPoint. Pourquoi cette implémentation n'est pas autorisée?

salutations, Kate

Répondre

3

En réponse à votre commentaire, sur la façon d'obtenir le meilleur des deux mondes; Je pensais à quelque chose comme ceci, où vous implémentez votre propriété GetPoints d'interface de manière explicite, créez une propriété GetPoints qui est plus typée et une méthode abstraite protégée que vous pouvez remplacer dans les implémentations concrètes.
Les 2 propriétés appellent l'implémentation abstraite.

public abstract class PointList<T> : IPointList where T : IPoint 
    { 
     public IList<T> GetPoints 
     { 
      get 
      { 
       return GetPointsCore(); 
      } 
     } 

     IList<IPoint> IPointList.GetPoints 
     { 
      get 
      { 
       return GetPointsCore() as IList<IPoint>; 
      }   
     } 

     protected abstract IList<T> GetPointsCore();   
    } 
+0

Élégant. Merci c'est exactement ce que je recherchais et ça fonctionne comme un charme. – SmartK8

+0

Cela pourrait toujours retourner null lorsqu'il est utilisé comme ceci: {PointList liste = new PointList (); var x = ((liste IPointList)) .GetPoints; } dans ce cas, x sera nul, car IList ne peut pas être converti en IList (au moins pas avant C# 4.0 dans VS 2010). – configurator

+0

Maintenant que j'y pense, cela ne fonctionnerait pas en C# 4.0 non plus parce qu'un IList n'est pas covariant. – configurator

2

La classe PointList devrait implémenter l'interface IPointList. Les méthodes/propriétés ne peuvent pas différer selon le type de retour uniquement, ce que vous essayez de faire avec la déclaration Points dans la classe PointList. Si vous implémentez

List<TPointType> Points { get; } 

alors vous pouvez logiquement ne pas mettre en œuvre

List<IPoint> Points { get; } 

parce qu'ils diffèrent selon le type de retour seulement.

+0

Ok. Donc, l'interface - en ce qui concerne les types - doit être telle qu'elle est. Est-il possible d'avoir le meilleur des deux mondes. Donc, les descendants peuvent avoir des génériques et l'interface est également satisfaite? Parce que de cette façon, je dois avoir des points et aussi d'autres propriétés Liste GenericPoints? – SmartK8

+0

Rendez l'interface générique. –

+0

Dans mon cas, les interfaces génériques sont une route vers l'enfer. J'ai essayé cela d'abord je me suis retrouvé avec six paramètres de longues interfaces. Cet exemple n'est pas ce que j'essaie vraiment de mettre en œuvre (ce qui rend plusieurs multitudes plus complexes). Merci pour le commentaire tu. – SmartK8