2009-09-08 16 views
6

L'interfaccia IList richiede un metodo Add. Le matrici implementano questa funzione ma semplicemente lancia una NotImplementedException. Questo mi sembra un pessimo design.Perché gli array supportano IList?

Cosa stavano pensando i progettisti quando l'hanno fatto?

risposta

7

Gli oggetti possono essere in sola lettura, in caso di dubbio il chiamante può testare la proprietà IsFixedSize prima di tentare di aggiungere o rimuovere un elemento o la proprietà IsReadOnly prima di tentare di modificare un elemento.

Un array è un IList di dimensioni fisse.

Può essere conveniente essere in grado di trattare un array come un elenco. Un esempio è il mocking di un metodo di accesso ai dati che restituisce un IList - può essere deriso per restituire semplicemente un cast di matrice come un IList.

+1

In realtà è la proprietà 'IsFixedSize' che dovresti controllare. 'IsReadOnly' sarà' false' per gli array perché gli elementi esistenti possono essere modificati. 'IsFixedSize' sarà' true' perché gli elementi non possono essere aggiunti o rimossi. – LukeH

+0

Giusto per chiarire il problema con fixed e read only: http://blogs.msdn.com/ericlippert/archive/2009/08/27/what-s-the-difference-between-fixed-and-fixed.aspx – Oliver

+1

@Oliver: Sono un grande fan del blog di Eric Lippert, ma quell'articolo non ha assolutamente nulla a che fare con le proprietà 'IsFixedSize' o' IsReadOnly'. – LukeH

0

Poiché è comune che diversi oggetti abbiano diverse abilità, alcune interfacce includono membri che verranno implementati da alcune ma non tutte le implementazioni. Se alcune, ma non tutte, le implementazioni di un'interfaccia ipotetica IVehicle sarebbero in grado di allegare un trailer, uno schema tipico sarebbe definire la funzione di AttachTrailer come "Tentativo di collegare un trailer, se CanAttachTrailer è vero, oppure lanciare NotSupportedException" . Tutte le implementazioni di IVehicle sarebbero in grado di soddisfare le specifiche di cui sopra, indipendentemente dal fatto che possano gestire i rimorchi.

Un vantaggio di questo approccio è che è possibile implementare un'interfaccia per offrire diverse combinazioni di funzionalità, senza dover definire tipi diversi per combinazioni diverse. Un altro vantaggio di questo approccio è che è possibile per un metodo Foo che riceve un oggetto che include funzionalità che non è necessario a Foo, per passare quell'oggetto al metodo Bar, che richiede tali funzionalità, senza richiedere alcun tipo di digitazione ovunque, e senza Foo sapendo quali sono le capacità Bar necessarie. Un altro vantaggio è che rende facile scrivere codice che non ha bisogno di determinate funzionalità, ma può trarne vantaggio quando esistono.

Ci sono alcuni svantaggi di questo approccio, tuttavia. Non esiste ancora un modo per un'interfaccia per specificare le implementazioni predefinite per qualsiasi proprietà o metodo. Di conseguenza, anche le implementazioni IVehicle che non possono allegare rimorchi dovranno includere il codice per restituire false alla proprietà CanAttachTrailer e generare un'eccezione nel loro metodo AttachTrailer. Inoltre, poiché l'interfaccia non impone alcun requisito per l'implementazione di molti dei suoi metodi, non è possibile che un compilatore possa ignorare il tentativo di chiamare una funzione che richiede una capacità con un oggetto di un tipo che non può fornirlo.

Durante la progettazione di IList<T>, Microsoft ha apparentemente pensato che i vantaggi dell'interfaccia "opzionalità opzionale" superassero gli svantaggi. Infatti, se .net fornisse un mezzo per le classi che implementano interfacce per rimandare a implementazioni predefinite di membri che non desiderano fornire, ci sarebbe un piccolo motivo per non includere molte funzionalità opzionali nelle interfacce di livello base; per consentire l'applicazione in fase di compilazione delle capacità necessarie, si potrebbe avere un numero di interfacce derivare da una base che include tutti i membri necessari e specificare che le classi che implementano le ultime interfacce devono implementare determinati membri in modi effettivamente utili. Ad esempio, Microsoft avrebbe potuto definire IResizableList<T> per ereditare IList<T> senza aggiungere alcun membro, ma con l'aspettativa che le implementazioni IList<T> che consentivano il ridimensionamento implementassero quest'ultima interfaccia, mentre quelle che non consentivano il ridimensionamento non l'avrebbero implementata.Se lo avessero fatto, il codice che doveva essere in grado di ridimensionare un elenco potrebbe richiedere un IResizableList<T> (nel qual caso non accetterebbe un array), mentre il codice che non ha bisogno di ridimensionare un elenco potrebbe richiedere un IList<T>). Sfortunatamente, Microsoft non ha fatto nulla del genere, quindi non è possibile che il codice richieda una lista ridimensionabile in fase di compilazione - tutto ciò che può fare è schiamazzare se un elenco passato si presenta come a dimensione fissa.

Problemi correlati