Interfaccia o classe di ritorno


9

Supponiamo che io abbia un metodo

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

    // some database stuff

    return users;
}

Ho letto che sarebbe meglio restituire un'interfaccia (o IListo IEnumerable) invece di restituire a List. Alcuni argomenti che ho sentito per farlo sono che nasconde i dati e offre allo sviluppatore API la flessibilità di modificare la rappresentazione interna dei dati in un secondo momento.

La mia preoccupazione per la restituzione di una IEnumerableè che si perde funzionalità, come l'accesso casuale e la Countproprietà.

So che accettare un IEnumerableparametro come ha un senso, in quanto offre al consumatore la massima flessibilità per inviare dati al mio metodo, l'insieme minimalista di requisiti per il funzionamento del metodo.

Qual è la migliore pratica per il tipo di reso?


5
Molto più importante: prendere un'interfaccia come tipo di parametro.
Michael Borgwardt,

Risposte:


10

In generale, puoi iniziare con le interfacce e passare a mettere il tipo concreto come tipo di ritorno se scopri che usi i metodi extra più frequentemente del previsto.

Bene, se si restituisce un'interfaccia, si mantiene una maggiore flessibilità. È possibile modificare l'implementazione in un secondo momento per restituire un diverso tipo di calcestruzzo. D'altra parte, ovviamente fornisce al chiamante meno informazioni, quindi potrebbero non essere in grado di eseguire determinate operazioni. (Ad esempio: se si ritorna List<T>, il chiamante può utilizzare ConvertAll ecc., Cosa che non può fare se si dichiara solo che si ritorna IList<T>.) In alcune situazioni vale la pena specificare il tipo concreto.

Per quanto riguarda il metodo Count o Sort, non esistono interfacce di raccolta standard per questo. Tuttavia, è possibile scrivere un metodo di estensione per ordinare o contare qualsiasi IList.


Immagino che questa non sia davvero una regola difficile, allora?
Matteo,

sì, dipende davvero dall'uso.
Yusubov,

1

Se hai bisogno della tua collezione per averne uno Countche puoi usare ICollection<T>, il che è abbastanza generale.


-1. Il conteggio è già stato discusso e questa risposta non aggiunge nulla di nuovo
superM

@Konrad Rudolph, questa non è una risposta, è un commento.
superM

@superM È abbastanza prezioso da meritare la propria risposta, penso, dal momento che affronta esplicitamente la ragione di OP nel decidere in primo luogo contro le interfacce.
Konrad Rudolph,

1

Restituisci ciò che è prudente per il metodo che stai definendo. Quello che stai facendo è restituire una serie di articoli (il focus è sugli articoli) o sta restituendo una collezione di articoli (il focus è sulla collezione nel suo insieme)? Vale la pena consentire una varianza nell'attuazione della collezione? Se non ha mai senso usare un generatore o HashSetsemplicemente usare il List.


1

Specifico per il metodo di esempio: hai ragione nel IEnmuerable<T>dire che il ritorno significherebbe perdere la funzionalità Counte l'indicizzazione (anche se potresti usare i metodi LINQ Count()e ElementAt(), che sono implementati in modo efficiente se il tipo su cui vengono effettivamente implementati IList<T>).

Se tornassi IList<T>, perderai alcune funzionalità, ma il guadagno in generale probabilmente ne vale la pena.

Ma ancora meglio sarebbe qualcosa tra IEnumerable<T>e IList<T>, perché molto probabilmente non ha senso per il consumatore mutare la raccolta restituita, ma ha senso per lui usare Counto indicizzare.

In .Net 4.5, non v'è tale interfaccia: IReadOnlyList<T>.


IReadOnlyListsuona bene quando posso ottenere VS2013, grazie!
Matteo,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.