Domanda

Sto cercando di implementare un metodo helper usando generics (C # / 3.5) Ho una bella struttura di classi, con classi di base come queste:

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

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

public class SomeNiceObjectCollection : CollectionBase<SomeNiceObject>
{

}

E desidero recuperare la raccolta usando un metodo generico come questo:

    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;          
     }
   }

Questo non si costruisce, con

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'oggetto SomeNiceObjectCollection È un CollectionBase, un CollectionBase per l'esattezza. Quindi, come posso farlo funzionare?

È stato utile?

Soluzione

C # non supporta il casting tra tipi di elenchi (covarianza).

La soluzione migliore per supportare questo modello sarebbe quella di introdurre un'interfaccia per il metodo ReadAllFromDatabase in modo da non fare affidamento su una raccolta generica:

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;          
 }
}

Altri suggerimenti

In C # 3.0 questo non è possibile, ma con C # e .NET 4.0 con covarianza e contraddizione, ciò potrebbe essere possibile.

Pensaci, stai prendendo una raccolta contenente un oggetto derivato e stai provando a trattarlo temporaneamente come una raccolta dell'oggetto base. Se ciò fosse consentito, è possibile inserire oggetti di base nell'elenco, che non sarebbe dell'oggetto derivato.

Ecco un esempio:

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!
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top