Guida al Visual Basic .NET
Capitolo 17° - Le Strutture
Nel capitolo precedente ci siamo soffermati ad analizzare una particolare categoria di tipi di dato, gli enumeratori, strumenti capaci di rappresentare tramite costanti numeriche possibilità, scelte, opzioni, flags e in genere valori che si possano scegliere in un insieme finito di elementi. Le strutture, invece, appartengono ad un'altra categoria. Anch'esse rappresentano un tipo di dato derivato, o complesso, poiché non rientra fra i tipi base (di cui ho già parlato) ma è da essi composto. Le strutture ci permettono di creare nuovi tipi di dato che possano adattarsi in modo migliore alla logica dell'applicazione che si sta scrivendo: in realtà, quello che permettono di fare è una specie di "collage" di variabili. Ad esempio, ammettiamo di voler scrivere una rubrica, in grado di memorizzare nome, cognome e numero di telefono dei nostri principali amici e conoscenti. Ovviamente, dato che si tratta di tante persone, avremo bisogno di array per contenere tutti i dati, ma in che modo li potremmo immagazzinare? Per quello che ho illustrato fino a questo punto, la soluzione più lampante sarebbe quella di dichiarare tre array, uno per i nomi, uno per i cognomi e uno per i numeri telefonici. Dim Names() As String Dim Surnames() As String Dim PhoneNumbers() As StringInutile dire che seguendo questo approccio il codice risulterebbe molto confusionario e poco aggiornabile: se si volesse aggiungere, ad esempio, un altro dato, "data di nascita", si dovrebbe dichiarare un altro array e modificare pressoch? tutte le parti del listato. Usando una struttura, invece, potremmo creare un nuovo tipo di dato che contenga al suo interno tutti i campi necessari: Structure Contact Dim Name, Surname, PhoneNumber As String End Structure '... 'Un array di conttati, ognuno rappresentato dalla struttura Contact Dim Contacts() As ContactCome si vede dall'esempio, la sintassi usata per dichiarare una struttura è la seguente: Structure [Nome] Dim [Campo1] As [Tipo] Dim [Campo2] As [Tipo] '... End StructureUna volta dichiarata la struttura e una variabile di quel tipo, però, come si fa ad accedere ai campi in essa presenti? Si usa l'operatore punto ".", posto dopo il nome della variabile: Module Module1 Structure Contact Dim Name, Surname, PhoneNumber As String End Structure Sub Main() Dim A As Contact A.Name = "Mario" A.Surname = "Rossi" A.PhoneNumber = "333 33 33 333" End Sub End Module[Ricordate che le dichiarazioni di nuovi tipi di dato (fino ad ora quelli che abbiamo analizzato sono enumeratori e strutture, e le classi solo come introduzione) possono essere fatte solo a livello di classe o di namespace, e mai dentro ad un metodo.] Una struttura, volendo ben vedere, non è altro che un agglomerato di più variabili di tipo base e, cosa molto importante, è un tipo value, quindi si comporta esattamente come Integer, Short, Date, eccetera... e viene memorizzata direttamente sullo stack, senza uso di puntatori. Acrobazie con le struttureMa ora veniamo al codice vero e proprio. Vogliamo scrivere quella rubrica di cui avevo parlato prima, ecco un inizio:Module Module1 Structure Contact Dim Name, Surname, PhoneNumber As String End Structure Sub Main() 'Contacts(-1) inizializza un array vuoto, 'ossia con 0 elementi Dim Contacts(-1) As Contact Dim Command As Char Do Console.Clear() Console.WriteLine("Rubrica -----") Console.WriteLine("Selezionare l'azione desiderata:") Console.WriteLine("N - Nuovo contatto;") Console.WriteLine("T - Trova contatto;") Console.WriteLine("E - Esci.") Command = Char.ToUpper(Console.ReadKey().KeyChar) Console.Clear() Select Case Command Case "N" 'Usa ReDim Preserve per aumentare le dimensioni 'dell'array mentenendo i dati già presenti. 'L'uso di array e di redim, in questo caso, è 'sconsigliato, a favore delle più versatili 'Liste, che però non ho ancora introdotto. 'Ricordate che il valore specificato tra 'parentesi indica l'indice massimo e non 'il numero di elementi. 'Se, all'inizio, Contacts.Length è 0, 'richiamando ReDim Contacts(0), si aumenta 'la lunghezza dell'array a uno, poiché 'in questo caso l'indice massimo è 0, 'ossia quello che indica il primo e 'l'unico elemento ReDim Preserve Contacts(Contacts.Length) Dim N As Contact Console.Write("Nome: ") N.Name = Console.ReadLine Console.Write("Cognome: ") N.Surname = Console.ReadLine Console.Write("Numero di telefono: ") N.PhoneNumber = Console.ReadLine 'Inserisce nell'ultima cella dell'array 'l'elemento appena creato Contacts(Contacts.Length - 1) = N Case "T" Dim Part As String Console.WriteLine("Inserire nome o cognome del " & _ "contatto da trovare:") Part = Console.ReadLine For Each C As Contact In Contacts 'Il confronto avviene in modalità 'case-insensitive: sia il nome/cognome 'che la stringa immessa vengono 'ridotti a Lower Case, così da 'ignorare la differenza tra 'minuscole e maiuscole, qualora presente If (C.Name.ToLower() = Part.ToLower()) Or _ (C.Surname.ToLower() = Part.ToLower()) Then Console.WriteLine("Nome: " & C.Name) Console.WriteLine("Cognome: " & C.Surname) Console.WriteLine("Numero di telefono: " & C.PhoneNumber) Console.WriteLine() End If Next Case "E" Exit Do Case Else Console.WriteLine("Comando sconosciuto!") End Select Console.ReadKey() Loop End Sub End ModuleOra ammettiamo di voler modificare il codice per permettere l'inserimento di più numeri di telefono: Module Module1 Structure Contact Dim Name, Surname As String 'Importante: NON è possibile specificare le dimensioni 'di un array dentro la dichiarazione di una struttura. 'Risulta chiaro il motivo se ci si pensa un attimo. 'Noi stiamo dichiarando quali sono i campi della struttura 'e quale è il loro tipo. Quindi specifichiamo che 'PhoneNumbers è un array di stringhe, punto. Se scrivessimo 'esplicitamente le sue dimensioni lo staremmo creando 'fisicamente nella memoria, ma questa è una 'dichiarazione, come detto prima, e non una 'inizializzazione. Vedremo in seguito che questa 'differenza è molto importante per i tipi reference '(ricordate, infatti, che gli array sono tipi reference). Dim PhoneNumbers() As String End Structure Sub Main() Dim Contacts(-1) As Contact Dim Command As Char Do Console.Clear() Console.WriteLine("Rubrica -----") Console.WriteLine("Selezionare l'azione desiderata:") Console.WriteLine("N - Nuovo contatto;") Console.WriteLine("T - Trova contatto;") Console.WriteLine("E - Esci.") Command = Char.ToUpper(Console.ReadKey().KeyChar) Console.Clear() Select Case Command Case "N" ReDim Preserve Contacts(Contacts.Length) Dim N As Contact Console.Write("Nome: ") N.Name = Console.ReadLine Console.Write("Cognome: ") N.Surname = Console.ReadLine 'Ricordate che le dimensioni dell'array non 'sono ancora state impostate: ReDim N.PhoneNumbers(-1) 'Continua a chiedere numeri di telefono finché 'non si introduce più nulla Do ReDim Preserve N.PhoneNumbers(N.PhoneNumbers.Length) Console.Write("Numero di telefono " & N.PhoneNumbers.Length & ": ") N.PhoneNumbers(N.PhoneNumbers.Length - 1) = Console.ReadLine Loop Until N.PhoneNumbers(N.PhoneNumbers.Length - 1) = "" 'Ora l'ultimo elemento dell'array è sicuramente 'vuoto, lo si dovrebbe togliere. Contacts(Contacts.Length - 1) = N Case "T" Dim Part As String Console.WriteLine("Inserire nome o cognome del " & _ "contatto da trovare:") Part = Console.ReadLine For Each C As Contact In Contacts If (C.Name.ToLower() = Part.ToLower()) Or _ (C.Surname.ToLower() = Part.ToLower()) Then Console.WriteLine("Nome: " & C.Name) Console.WriteLine("Cognome: " & C.Surname) Console.WriteLine("Numeri di telefono: ") For Each N As String In C.PhoneNumbers Console.WriteLine(" - " & N) Next Console.WriteLine() End If Next Case "E" Exit Do Case Else Console.WriteLine("Comando sconosciuto!") End Select Console.ReadKey() Loop End Sub End ModuleIn questi esempi ho cercato di proporre i casi più comuni di struttura, almeno per quanto si è visto fino ad adesso: una struttura formata da campi di tipo base e una composta dagli stessi campi, con l'aggiunta di un tipo a sua volta derivato, l'array. Fino ad ora, infatti, ho sempre detto che la struttura permette di raggruppare più membri di tipo base, ma sarebbe riduttivo restringere il suo ambito di competenza solo a questo. In realtà può contenere variabili di qualsiasi tipo, comprese altre strutture. Ad esempio, un contatto avrebbe potuto anche contenere l'indirizzo di residenza, il quale avrebbe potuto essere stato rappresentato a sua volta da un'ulteriore struttura: Structure Address Dim State, Town As String Dim Street, CivicNumber As String Dim Cap As String End Structure Structure Contact Dim Name, Surname As String Dim PhoneNumbers() As String Dim Home As Address End StructurePer accedere ai campi di Home si sarebbe utilizzato un ulteriore punto: Dim A As Contact A.Name = "Mario" A.Surname = "Rossi" ReDim A.PhoneNumbers(0) A.PhoneNumbers(0) = "124 90 87 111" A.Home.State = "Italy" A.Home.Town = "Pavia" A.Home.Street = "Corso Napoleone" A.Home.CivicNumber = "96/B" A.Home.Cap = "27010"
C#, TypeScript, java, php, EcmaScript (JavaScript), Spring, Hibernate, React, SASS/LESS, jade, python, scikit, node.js, redux, postgres, keras, kubernetes, docker, hexo, etc...
|