Utilisation d'objets de base en tant que paramètres dans une fonction générique

StackOverflow https://stackoverflow.com/questions/1410579

  •  05-07-2019
  •  | 
  •  

Question

J'essaie d'implémenter une méthode d'assistance à l'aide de génériques (C # / 3.5) J'ai une belle structure de classes, avec des classes de base comme celles-ci:

public class SomeNiceObject : ObjectBase
{
  public string Field1{ get; set; }
}

public class CollectionBase<ObjectBase>()
{
  public bool ReadAllFromDatabase();
}

public class SomeNiceObjectCollection : CollectionBase<SomeNiceObject>
{

}

Et je souhaite récupérer la collection en utilisant une méthode générique comme celle-ci:

    public class DAL
    {

     public SomeNiceObjectCollection Read()
     {
      return ReadFromDB<SomeNiceObjectCollection>();
     }

     T ReadFromDB<T>() where T : CollectionBase<ObjectBase>, new()
     {
      T col = new T();
      col.ReadAllFromDatabase();
      return col;          
     }
   }

Cela ne construit pas, avec

Error   66  The type 'SomeNiceObjectCollection' cannot be used as type parameter 'T' in the generic type or method 'ReadFromDB<T>'.   There is no implicit reference conversion from 'SomeNiceObjectCollection' to 'CollectionBase<ObjectBase>'.

L'objet SomeNiceObjectCollection EST un CollectionBase, un CollectionBase pour être exact. Alors, comment puis-je obtenir que cela fonctionne?

Était-ce utile?

La solution

C # ne prend pas en charge la conversion entre les types de liste (covariance).

Votre meilleur choix pour prendre en charge ce modèle serait d'introduire une interface pour la méthode ReadAllFromDatabase afin que vous ne vous reposiez pas sur une collection générique:

public class SomeNiceObject : ObjectBase
{
  public string Field1{ get; set; }
}

public interface IFromDatabase
{
  bool ReadAllFromDatabase();
}

public class CollectionBase<ObjectBase>() : IFromDatabase
{
  public bool ReadAllFromDatabase();
}

public class SomeNiceObjectCollection : CollectionBase<SomeNiceObject>
{

}

public class DAL
{

 public SomeNiceObjectCollection Read()
 {
  return ReadFromDB<SomeNiceObjectCollection>();
 }

 T ReadFromDB<T>() where T : IFromDatabase, new()
 {
  T col = new T();
  col.ReadAllFromDatabase();
  return col;          
 }
}

Autres conseils

En C # 3.0, cela n’est pas possible, mais avec C # et .NET 4.0 avec covariance et contravariance, cela pourrait être possible.

Pensez-y, vous prenez une collection contenant un objet dérivé et essayez de la traiter temporairement comme une collection de l'objet de base. Si cela était autorisé, vous pourriez insérer des objets de base dans la liste, qui ne seraient pas de l'objet dérivé.

Ici, un exemple:

List<String> l = new List<String>();
List<Object> o = l;
l.Add(10); // 10 will be boxed to an Object, but it is not a String!
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top