sexta-feira, 8 de outubro de 2010

Como passar lista de objetos de classe derivada para método que recebe lista objetos de classe base

Se você tem um método que recebe um parâmetro List<T>, e quer passar para este método uma lista List<T1>, aonde T1 é derivada de T, então continue lendo. (Se não, pode voltar ao que você estava fazendo ;-)

Criei o seguinte método:
public static void IncluiEntidades(List<EntidadeAzureTable> entidades)
{
...
}
EntidadeAzureTable é a classe base de várias outras na aplicação. Este método recebe uma lista de entidades e as grava nas respectivas tabelas (no Azure Table Service).

Pois bem, criei uma lista de objetos de uma classe derivada e tentei passá-la para o método acima:

List<DocumentoSaida> documentos; // DocumentoSaida deriva de EntidadeAzureTable
documentos = ...;
AzureTables.IncluiEntidades(documentos);
O compilador do C# não deixou passar, retornando o seguinte erro de compilação:

Argument 1: cannot convert from 'System.Collections.Generic.List<DocumentoSaida>' to 'System.Collections.Generic.List<EntidadeAzureTable>'

Ele “não entendeu” que DocumentoSaida herda de EntidadeAzureTable. Aparentemente, se um método recebe um parâmetro que é uma lista de objetos de uma classe, não posso passar uma lista de objetos de uma classe derivada neste parâmetro.

Para resolver este problema, podemos utilizar generic type constraints: criar um método genérico, e usar a palavra-chave where para colocar uma restrição no parâmetro de tipo do método. Mudei a declaração do método para

public static void IncluiEntidades<T>(List<T> entidades)
     where T : EntidadeAzureTable
{
   ...
}
e o compilador entendeu o que eu estava querendo fazer.