252 messaggi dal 03 dicembre 2001
www.fuossbook.it
Ciao a tutti,
c'é u n passaggio nel mio studio e nei miei esercizi che ancora non mi é chiaro al 100%,
ovvero quando utilizzare e come ICollection, IEnumerable , List ed Enum.
Online trovo qualche piccolo articolo (in inglese) che fa le differenze ICollection e IEnumerable ma onestamente non mi è ancora molto chiaro tutto.
Qualcuno mi può dire quando conviene usarle e soprattutto quale il risultato finale del loro utilizzo.
Grazie

***************************
webmaster di:
hydrasail.blogspot.it
fuossbook.it
***************************
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao,
partiamo da una premessa: in programmazione, come anche nella vita reale, si cerca di usare lo strumento appropriato alla situazione, che faccia esattamente quello che serve e non di più perché potrebbe "costarci troppo".
E' il principio del privilegio minimo, lo stesso che per esempio ti porta ad andare in vacanza solo con l'indispensabile, perché portarsi altre cose superflue sarebbe un peso e una distrazione.

Ora, un oggetto che implementa ICollection<T> si porta appresso già un bel peso: l'oggetto è in grado di dirti a priori quanti elementi contiene e ti permette di aggiungere, rimuovere e cercare gli elementi in esso.
In un certo senso, se un tuo metodo restituisce un ICollection<T>, stai permettendo a chiunque di rovistare nella tua valigia e di aggiungere/togliere roba a loro discrezione. Se non sei in grado di proteggere il contenuto della tua valigia dagli sconosciuti, potresti trovarti sorprese in aeroporto.

Con un IEnumerable<T>, invece, l'oggetto ha solo l'obbligo di presentare i suoi oggetti in maniera forward-only (l'elenco può essere scorso solo in avanti) e in sola lettura. Il contenuto della tua valigia può comunque essere osservato come quando passa sul nastro trasportatore del controllo bagagli, ma gli altri presenti non possono alterarlo in nessun modo*. Così mantieni la giurisdizione sul contenuto della valigia e nessun altro può dirti cosa metterci (a meno che non sia tu a volerlo).

Quindi, scegliere ICollection<T> o IEnumerable<T> come tipo restituito dai tuoi metodi e dalle tue proprietà, serve a comunicare al mondo esterno quali sono i loro privilegi nei confronti dell'oggetto che restituisci. Vuoi che siano in grado di scombussolarti la valigia? Restituisci un ICollection<T> oppure addirittura un IList<T>, il non plus ultra dello scombussolamento, che supporta anche l'accesso randomico (la possibilità di andarti a sostituire il dentifricio senza dover frugare prima tra gli altri oggetti presenti in valigia).

Se invece vuoi che dall'esterno si possa guardare ma non toccare, allora restituisci un oggetto che implementa giusto IEnumerable<T>. Così sarai più pragmatico ed eviterai molti bug.

ciao,
Moreno

*Tranne che con la reflection, ma anche in questo caso dipende.
Modificato da BrightSoul il 07 giugno 2017 19.49 -

Enjoy learning and just keep making
252 messaggi dal 03 dicembre 2001
www.fuossbook.it
Grazie Moreno
quindi se ho capito bene
ICollection, IEnumerable ecc contengono una lista di offetti
a differenza di list e enums che sono solo liste (come array)?

***************************
webmaster di:
hydrasail.blogspot.it
fuossbook.it
***************************
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao,


ICollection, IEnumerable ecc contengono una lista di offetti
a differenza di list e enums che sono solo liste (come array)?

No, andiamo con ordine.

Per prima cosa togliamo di mezzo le Enum, che non c'entrano niente in questo caso perché non sono liste di oggetti. Una Enum è un tipo che consente all'utilizzatore di indicare uno tra alcuni valori ammessi. E' come quando ti chiedono di indicare il sesso e tu puoi rispondere solo M o F.

Torniamo alle liste.
Quando dici "liste" o "liste di oggetti", in realtà stai parlando della stessa cosa. Per "lista" si intende appunto una lista di oggetti.

Prendiamo List<T>, per esempio.
var lista = new List<string>();
lista.Add("Gennaio");
lista.Add("Febbraio");
lista.Add("Marzo");
...

Come vedi, ho creato una lista e ci ho aggiunto delle stringhe, perché la lista era appunto una List<string>, cioè idonea ad accogliere oggetti stringa.

Si dice che List<T> è un tipo concreto, vuol dire che posso crearne un'istanza con la parola chiave new come ti ho fatto vedere. List<T> ha tante funzionalità ed è molto comoda perché mi permette di aggiungere, rimuovere e riordinare gli elementi che ci ho messo all'interno.

Ora ipotizziamo che tu scriva un metodo che restituisce la lista dei mesi.
public List<string> ListaMesi() {
   var lista = new List<string>();
   lista.Add("Gennaio");
   lista.Add("Febbraio");
   lista.Add("Marzo");
   ...
   return lista;
}


Questo metodo lo uso io, che sono uno sviluppatore di un'altra azienda che sta collaborando con te. Dato che mi restituisci una List<string>, mi stai dando in mano un oggetto che mi dà molto potere. Io, per farti un dispetto (ma a fin di bene, per insegnarti il principio del privilegio minimo) ti scombussolo i nomi dei mesi, te ne rimuovo alcuni e ci aggiungo "Smarzo" prima di restituirti la lista.

Ora, immagina il danno che puoi fare se questa, anziché essere una lista di mesi, fosse la lista di fatture che la tua azienda deve pagare alla mia. Potrei potenzialmente gonfiare i prezzi e far finta che mi devi più soldi del dovuto.

Allora, per evitare che io possa far danni, riscrivi il metodo in questo modo:
public IEnumerable<string> ListaMesi() {
   var lista = new List<string>();
   lista.Add("Gennaio");
   lista.Add("Febbraio");
   lista.Add("Marzo");
   ...
   return lista;
}

In questo modo mi stai dando in mano un oggetto che implementa IEnumerable<string>, cioè che non ha i metodi Add e Remove di List<T>. Quello che io posso farci è solo un foreach per leggermi i nomi dei mesi nell'ordine che TU hai stabilito e BASTA.

IEnumerable<T> e ICollection<T> non sono tipi concreti, cioè non ne posso creare un'istanza con la parola chiave new. Invece, sono delle interfacce implementate da oggetti come List<T> e Array che descrivono quali funzionalità offrono.

Per il fatto che List<T> implementa IEnumerable<T>, mi dà la garanzia che io possa ciclare questa collezione con un foreach. Il fatto che implementa ICollection<T>, mi garantisce che io possa conoscere a priori il numero di elementi in essa e che tali elementi si possano aggiungere ed eliminare.
Come lo so? Dai membri che risultano nella documentazione:
https://msdn.microsoft.com/it-it/library/9eekhta0(v=vs.110).aspx
https://msdn.microsoft.com/it-it/library/92t2ye13(v=vs.110).aspx

Una classe come List<T> che implementa un'interfaccia ha l'obbligo di esporre come pubblici i membri definiti nell'interfaccia.
Una classe come List<T> può essere vista come una delle interfacce che implementa. Nel mio esempio, sto usando una List<T> per crearmi una lista dei mesi, però poi il metodo la restituisce come IEnumerable<T>, affinché dall'esterno non si possa alterare, ma solo leggere. E' un modo per limitare le abilità di chi usa il tuo codice. Limitare vuol dire semplicità, così che l'utente non sia confuso da troppe possibilità, e anche sicurezza perché così è limitato a stare nei binari che tu gli hai tracciato.

Per rafforzare le tue basi, leggi innanzitutto a proposito delle interfacce:
https://docs.microsoft.com/it-it/dotnet/csharp/programming-guide/interfaces/index

Delle classi:
https://docs.microsoft.com/it-it/dotnet/csharp/programming-guide/classes-and-structs/classes

E di uno dei principi della programmazione orientata agli oggetti: il polimorfismo.
https://docs.microsoft.com/it-it/dotnet/csharp/programming-guide/classes-and-structs/polymorphism

ciao,
Moreno
Modificato da BrightSoul il 09 giugno 2017 20.01 -

Enjoy learning and just keep making

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.