Perché IList non supporta AddRange


89

List.AddRange()esiste, ma IList.AddRange()non lo è.
Questo mi sembra strano. Qual è il motivo dietro questo?

Risposte:


68

Perché un'interfaccia deve essere facile da implementare e non contenere "tutto tranne la cucina". Se aggiungi AddRangedevi aggiungere InsertRangee RemoveRange(per simmetria). Una domanda migliore sarebbe perché non ci sono metodi di estensione per l' IList<T>interfaccia simili IEnumerable<T>all'interfaccia. (metodi di estensione per in-place Sort, BinarySearch, ... sarebbe utile)


35
@ShdNx Non sono molto banali da implementare dal punto di vista delle prestazioni. Un "interno" AddRange/RemoveRange/InsertRangepuò lavorare direttamente sulla raccolta "interna" e ottimizzare la Capacitygestione e utilizzare metodi come Array.Copyspostare blocchi di dati. Un metodo di estensione RemoveRangesarebbe probabilmente un ordine di grandezza più lento diList.RemoveRange
xanatos

2
È un peccato che non ci fosse (e ancora non lo sia) alcun modo per una IFoodichiarazione di interfaccia (ad esempio ) per specificare uno spazio dei nomi "helper" (ad esempio MyAssembly) tale che se una classe dichiara di implementare IFooma manca di metodo int Bar(String), il compilatore si auto- generare metodo int IFoo.Bar(String p1) {return MyAssembly.ClassHelpers.IFoo.Bar(this, p1);} Se una tale caratteristica fosse esistita, le interfacce avrebbero potuto includere più metodi come quelli AddRangeche potrebbero essere implementati in termini di un comportamento di base, ma che alcune implementazioni potrebbero ottimizzare.
supercat

1
Potrebbero essere implementati come metodi di estensione, in questo modo l'implementazione dell'interfaccia non dovrebbe implementarli. Perché non lo sono?
Tom Pažourek

15
Questo non ha senso. Un'interfaccia astrae un'implementazione, in modo che possano esserci più implementazioni delle stesse funzionalità di base; non c'è motivo per cui le funzionalità dovrebbero essere omesse da un'interfaccia, perché "l'implementazione è difficile". Senza metodi come "AddRange" sull'interfaccia, non vi è alcuna garanzia che l'oggetto sottostante li supporti, ea quel punto sei costretto a implementare un'estensione subottimale o annullare lo scopo di utilizzare un'interfaccia facendo ipotesi pericolose cercando di cast a una specifica classe di implementazione. Le interfacce stupide sono sovrautilizzate.
Triynko

3
Dovrebbe esserci l'interfaccia IRangeList che supporta le operazioni di massa, implementata solo su alcune raccolte che internamente avranno l'implementazione ottimale.
anche il

8

Per coloro che desiderano avere metodi di estensione per "AddRange", "Sort", ... su IList,

Di seguito è riportato il AddRangemetodo di estensione:

 public static void AddRange<T>(this IList<T> source, IEnumerable<T> newList)
 {
     if (source == null)
     {
        throw new ArgumentNullException(nameof(source));
     }

     if (newList == null)
     {
        throw new ArgumentNullException(nameof(newList));
     }

     if (source is List<T> concreteList)
     {
        concreteList.AddRange(newList);
        return;
     }

     foreach (var element in newList)
     {
        source.Add(element);
     }
}

Ho creato una piccola libreria che fa questo. Lo trovo più pratico che dover ripetere i suoi metodi di estensione su ogni progetto.

Alcuni metodi sono più lenti di List ma fanno il lavoro.

Ecco il GitHub per interessarli:

Repository IListExtension

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.