Pergunta

Eu estou tentando implementar um método auxiliar usando os genéricos (C # / 3.5) Eu tenho uma estrutura agradável de aulas, com base classes assim:

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

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

public class SomeNiceObjectCollection : CollectionBase<SomeNiceObject>
{

}

E eu desejo a coleção retreive usando um método genérico assim:

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

Esta não construir, com

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>'.

O objeto SomeNiceObjectCollection é um CollectionBase, um CollectionBase para ser exato. Então, como posso chegar a este trabalho?

Foi útil?

Solução

C # não suporta a conversão entre tipos de lista (covariância).

Sua melhor aposta para suportar esse padrão seria a introdução de uma interface para o método ReadAllFromDatabase para que você não está confiando em uma coleção genérica:

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

Outras dicas

Em C # 3.0 isto não é possível, mas com C # e .NET 4.0 com covariância e contravariance, isso pode ser possível.

Pense nisso, você está tendo uma coleção que contém um objeto derivado, e tentar tratá-lo temporariamente como uma coleção do objeto base. Se isso era permitido, você pode inserir objetos base na lista, o que não seria do objeto derivado.

Aqui, um exemplo:

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!
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top