Interface ou classe de retorno

9

Suponha que eu tenha um método

public List<User> GetBatchOfUsers(IEnumerable<int> userIDs)
{
    List<User> users = new List<User>();

    // some database stuff

    return users;
}

Eu li que seria melhor retornar uma interface ( IListou IEnumerable) em vez de retornar a List. Alguns argumentos que ouvi falar disso são que ocultam dados e oferecem ao desenvolvedor da API a flexibilidade de alterar a representação interna dos dados posteriormente.

Minha preocupação em apenas retornar um IEnumerableé que você perde funcionalidades, como acesso aleatório e a Countpropriedade.

Sei que aceitar IEnumerableum parâmetro faz sentido, pois oferece ao consumidor a melhor flexibilidade para enviar dados ao meu método, o conjunto minimalista de requisitos para o método operar.

Qual é a melhor prática para o tipo de retorno?

Mateus
fonte
5
Muito mais importante: use uma interface como tipo de parâmetro.
Michael Borgwardt

Respostas:

10

De um modo geral, você pode começar com interfaces e mudar para colocar o tipo concreto como o tipo de retorno se achar que usa os métodos extras com mais frequência do que o esperado.

Bem, se você retornar uma interface, reterá mais flexibilidade. Você pode alterar a implementação posteriormente para retornar um tipo concreto diferente. Por outro lado, obviamente fornece menos informações ao chamador, para que ele não possa executar determinadas operações. (Por exemplo: se você retornar List<T>, o chamador poderá usar o ConvertAll etc ... que não poderá se você apenas declarar que retorna IList<T>.) Em algumas situações, vale a pena especificar o tipo concreto.

Em relação ao método Count ou Sort, não há interfaces de coleta padrão para isso. No entanto, você pode escrever um método de extensão para classificar ou contar qualquer IList.

Yusubov
fonte
Eu acho que isso não é realmente uma regra difícil, então?
Matthew
Sim, isso realmente depende do uso.
Yusubov 08/08/2012
1

Se você precisar da sua coleção, Countpoderá usá-lo ICollection<T>, o que é bastante geral.

dpiatkowski
fonte
-1. Contagem já foi discutido e esta resposta não acrescenta nada novo
SuperM
@ Konrad Rudolph, isso não é uma resposta, é um comentário.
SuperM
@superM É valioso o suficiente para merecer sua própria resposta, eu acho, uma vez que aborda explicitamente a razão da OP de decidir contra interfaces em primeiro lugar.
9289 Konrad Rudolph
1

Você devolve o que é prudente para o método que está definindo. O que você está fazendo está retornando uma série de itens (o foco está nos itens) ou está retornando uma coleção de itens (o foco está na coleção como um todo)? Vale a pena permitir variações na implementação da coleção? Se nunca fizer sentido usar um gerador ou HashSetapenas usar o List.

Telastyn
fonte
1

Específico ao método de exemplo: você está certo ao retornar IEnmuerable<T>, significando que perderia a funcionalidade Counte a indexação (embora você possa usar os métodos LINQ Count()e ElementAt(), que são implementados com eficiência se o tipo em que são realmente implementados IList<T>).

Se você retornasse IList<T>, perderia algumas funcionalidades, mas provavelmente o ganho em geral vale a pena.

Mas ainda melhor seria algo entre IEnumerable<T>e IList<T>, porque provavelmente não faz sentido para o consumidor alterar a coleção retornada, mas faz sentido para ele usar Countou indexar.

Em .Net 4.5, não há tal relação: IReadOnlyList<T>.

svick
fonte
IReadOnlyListparece bom quando posso obter o VS2013, obrigado!
Matthew