Usando base de objetos como parâmetros em uma função genérica
-
05-07-2019 - |
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?
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!