• Regolamento Macrocategoria DEV
    Prima di aprire un topic nella Macrocategoria DEV, è bene leggerne il suo regolamento. Sei un'azienda o un hosting/provider? Qui sono anche contenute informazioni per collaborare con Sciax2 ed ottenere l'accredito nella nostra community!

Guida Ordinare oggetti complessi

Mourne

Utente Attivo
Autore del topic
16 Giugno 2010
403
56
Miglior risposta
0
Salve,
questa che vi presenterò oggi è una "piccola" guida sull'ordinamento di oggetti complessi con array.

Sono richieste conoscenze base di VB.NET

Penso che alcuni scriveranno "bravo, complimenti ecc" senza aver letto, e vi capisco perchè è abbastanza lunga xD

Nelle ultime parti non vorrei aver fatto errori (anche se non dovrebbe essere successo) dato che era il punto in cui stavo per collassare :look:

Buona lettura :smile:



Iniziamo subito dicendo che la cosa più frequente che possa fare un programmatore è quella di ordinare degli oggetti in un array.
Questo non è difficile se basta soltanto organizzare una lista di stringhe o numeri in un array monodimensionale.
Quello che andremo a fare è utilizzare il metodo Array.Sort.

Creiamo una piccola classe di supporto intitolata CFiles. Questa classe possiede un solo metodo che è il GetFiles. Quest'ultimo riporta un array di oggetti FileInfo.

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

Fate attenzione all'istruzione di importazione che troveremo in ogni codice presente nella guida.
Da qui potete vedere come è semplice utilizzare questa classe:

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

Se avete tentato di utilizzare il metodo Array.Sort per sistemare l'array ff, VB.NET risponde con l'errore "Failed to compare two elements in the array".
Il motivo è che Sort non sa come strutturare un array di oggetti complessi: per questo motivo dobbiamo dargli noi un parametro per stabilire quando un oggetto array è maggiore di un altro

Il metodo Sort ha 17 overload diversi, che si distinguono per il numero e il tipo di parametri.
I parametri che dovremo collocare al metodo sono le array da ordinare e una classe che migliori l'interfaccia IComparer

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!


A questo punto creiamo una classe intitolata CSorter0 e inseriamo il codice qui sotto

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

In questo caso Compare riporta un valore dalla similitudine delle estensioni degli oggetti File1 e File2.

Questo blocco di codice, che viene effettuato quando clicchiamo sul pulsante Get Files crea un array di oggetti FileInfo usando il metodo GetFiles della classe Cfiles e ad aggiungerli a una ListBox

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

Quest'altro blocco di codice eseguito quando clicchiamo su Sort files, crea un'istanza di CSorter0 e la usa in Array.Sort.

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!


Mettiamo il caso che decidiamo di non volere una classe ordinata per estensione. Vogliamo una classe che permetta di selezionare la proprietà secondo la quale ordinare l'array, selezionare un ordinamento ascendente o discendente e se distinguere o meno tra maiuscole e minuscole.

Per fare tutto ciò, bisogna creare un tipo Enum che sia in grado di specificare le proprietà che possiamo usare per ordinare:

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

Fatto questo creiamo una nuova classe chiamata CSorter1 che inserisca l'interfaccia IComparer e che rispetto a CSorter0 abbia tre proprietà: DescendingOrder e IgnoreCase di tipo Boolean e CompareBy di tipo enCompareOptions.

Ora andiamo a controllare in Compare il valore CompareBy per utilizzare la proprietà, e il valore di DescendingOrder per invertire (se DescendingOrder = True) il modo in cui gli oggetti vengono comparati. Il valore di IgnoreCase viene usato nella comparazione di proprietà di tipo stringa. Attenzione: anche per proprietà di tipo DateTime, i confronti vengono fatti usando DateTime.Compare.

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!
Se vogliamo ordinare array di oggetti dello stesso tipo, siamo costretti ad avere una classe per ogni tipo di oggetto che si vuole ordinare.

Per superare questa complicazione c'è una tecnica che fa uso del metodo CallByName. Quest'ultimo era presente in VB6 e penso ci sia ancora in .Net Framework per motivi di compatibilità. Questo, richiama un metodo di un oggettospecificando il nome del metodo in una ben precisa stringa.

Il codice da inserire è questo:

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

ObjectRef è l'oggetto con cui vogliamo richiamare il metodo o la proprietà
ProcName è il nome del metodo/proprietà da richiamare.
UseCallType specifica il tipo di chiamata da eseguire.
Args è di tipo ParamArray e contiene tutte gli argomenti da esaminare per richiamare la proprietà

Qui leggeremo soltanto il valore di proprietà senza l'utilizzo del parametro Args.

Creiamo una nuova classe (che chiameremo Csorter2). Rispetto a CSorter1 essa conserverà le proprietà DescendingOrder e IgnoreCase, ma perderà CompareBy.

A CSorter2 dovremo passare il nome della proprietà da usare. Per semplificare il tutto ho inserito un tipo enumerativo (enPropType) che useremo per impostare il tipo della proprietà da usare per l'ordinamento

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

Nome e tipo della proprietà vengono impostati usando un unico metodo, anziché due property separate.

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

Nel metodo Compare, si usa CallByName per trovare il valore della proprietà impostata con SetSortProperty, che viene dato a una variabile:

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

Per semplificarvi la vita, ho chiarito e modificato i nomi degli oggetti che compaiono nella dichiarazione di Compare:

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

Ho impostato l'uso delle classi Type e PropertyInfo al posto di CallByName per trovare i valori della proprietà di un oggetto.

A questo punto creiamo un oggetto Type per accedere ai metadati dell'oggetto Obj1:

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

Abbiamo bisogno di un solo oggetto Type perché i parametri di Compare devono essere dello stesso tipo.

PropertyInfo, ci consente di usare un oggetto Type per ottenere informazioni su una specifica proprietà:

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

Ora, useremo il metodo GetValue dell'oggetto prop per ottenere il valore della proprietà in un oggetto del tipo Obj1 e Obj2

Aiutandovi ulteriormente, la proprietà è di tipo String che si può scrivere:

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

objArr è un array di oggetti richiesto da GetValue.

Rimane un ultimo piccolo problema da risolvere: il metodo GetProperty, al contrario di CallByName, è case-sensitive. Questo significa che potete a ordinare un array di oggetti FileInfo secondo la proprietà "FullName", ma non "fullname", perché "FullName" è il nome corretto della proprietà. Se si utilizza un nome di proprietà senza rispettare rigidamente questa regola, il programma darà un errore. Questo rende la classe piuttosto fragile, ma una soluzione c'è: la classe Type espone un metodo GetProperties che restituisce un array di oggetti PropertyInfo contenente tutte le proprietà dell'oggetto a cui l'oggetto Type si riferisce.

Passando alla pratica, andiamo ad aggiungere nel metodo Compare questa riga:

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

Ora controlliamo quale proprietà ha lo stesso nome del valore in _PropertyName. Una volta trovata, le assegnamo il nome alla variabile _PropertyName.

Infine, ecco una prima parte dell'ultimo adattamento nel Compare.

Codice:
Perfavore, Entra oppure Registrati per vedere i codici!

Questa ulteriore versione non modificherà il rendimento del programma.




Grazie per aver letto la mia guida per l'ordinazione di oggetti complessi. So che è un po' lunga ma ho fatto prima che creare più topic al riguardo :gururun:

Scusate ancora se ho saltato qualcosa (anche se non dovrebbe) ma sto stanchissimo per l'orario e la giornata faticosa :S



Cordialmente,
Mourne
 
Riferimento: Ordinare oggetti complessi

Perchè creare la funzione GetFiles se esiste già nella classe Directory ?