Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C# / VB.NET - Hashtable
Forum - C# / VB.NET - Hashtable

Avatar
Marcus65 (Normal User)
Newbie


Messaggi: 10
Iscritto: 30/08/2010

Segnala al moderatore
Postato alle 7:16
Lunedì, 30/08/2010
Salve sono nuovo del forum e anche di VB.NET che sto studiando (purtroppo nei ritagli di tempo) sull’ottima guida di Totem. Chiedo scusa in anticipo per la prolissità ma ho 2 problemi che non riesco proprio a risolvere. Se qualcuno volesse darmi una mano….
Sono alle prese con gli hastable e i metodi factory.  Ho creato programmino che calcola il peso di alcuni cubi.  C’è una classe cube con 3 campi private (e relative property) : Spigolo, Densità e l’hastable Cubes (Shared oltre che private). Dal main vengono creati alcuni oggetti A, B, C ecc. di tipo cube,  inizializzati attraverso un metodo factory. La mia prima domanda è la seguente:

1)    Perché il costruttore (richiamato dal metodo factory) va scritto

Private Sub New(ByVal Spig As Single, ByVal Ps As Single)
            Me._Spig = Spig
            Me._Ps = Ps
            _cubes.Add(Spig, Me)
        End Sub

'Non sarebbe sufficiente scrivere (eliminando il riferimento alla classe stessa “Me” ) ?

Private Sub New(ByVal Sp As Single, ByVal Ps As Single)
            Spig = Sp
            Ps = Ps
            cubes.Add(Spig, Ps)
        End Sub

La seconda domanda è la seguente:
2)    Se voglio visualizzare tutto l’hashtable cioè tutti i cubi dalla main, scrivo questo codice e funziona

For Each X As DictionaryEntry In cube.cubes
            Dim Y As cube = X.Value
            Console.WriteLine(Y.Spig)
            Console.WriteLine(Y.Ps)
            Console.WriteLine()
        Next

Ma se voglio visualizzare un cubo solo richiamandolo per chiave (spigolo) non so come fare. Per es per visualizzare il cubo di spigolo 1 ho provato con

Dim H As Hashtable = cube.cubes
Console.WriteLine(H(1.0))      

Cioè  dichiarando un hashtable inizializzandolo col nostro hashtable e andando a visualizzare l’elento richiesto. Ma che c’è che non va ?

Oppure con

Dim Y As cube = cube.cubes(3.0)
Console.WriteLine("Cubo A: " & Y.Ps)

D’altronde si tratta di un hashtable shared di oggetti cube. Quindi dichiaro l’oggetto Y, lo inzializzo con l’elemento dell’hashtable desiderato e poi vado a visualizzarlo. Perché non deve funzionare ?

Ultima modifica effettuata da Il Totem il 30/08/2010 alle 10:55
PM
Avatar
Marcus65 (Normal User)
Newbie


Messaggi: 10
Iscritto: 30/08/2010

Up
0
Down
V
Segnala al moderatore
Postato alle 15:28
Lunedì, 30/08/2010
Grazie per la chiarezza (consueta, del resto) riguardo alla risposta al punto 1.

Per quanto riguarda la seconda domanda  
Allora: se uso la soluzione

Dim H As Hashtable = cube.cubes
Console.WriteLine("Cubo A: " & H(1.0).Ps)

si genera il messaggio di errore "Variabile oggetto o variabile del blocco With non impostata."

se invece uso la

Dim Y As cube = cube.cubes(3.0)
Console.WriteLine("Cubo E: " & Y.Ps)

ottengo "Riferimento a un oggetto non impostato su un'istanza di oggetto."

D'altronde ho ragionato così: ho un'hashtable di oggetti cube, richiamo quello che mi interessa e poi mando a video il campo Ps (il campo spigolo l'ho usato come chiave. Non ha molto senso ma è solo un programma di prova)

Comunque ad evitare ogni possibile frintendimento, posto di seguito il sorgente o è preferibile che si invii il tutto in archivio .zip ?

Codice sorgente - presumibilmente VB.NET

  1. Module Module1
  2.     Class cube
  3.         Private _Spig, _Ps As Single
  4.         Private Shared _cubes As New Hashtable
  5.         ReadOnly Property Spig() As Single
  6.             Get
  7.                 Return _Spig
  8.             End Get
  9.         End Property
  10.         ReadOnly Property Ps() As Single
  11.             Get
  12.                 Return _Ps
  13.             End Get
  14.         End Property
  15.         Shared ReadOnly Property cubes() As Hashtable
  16.             Get
  17.                 Return _cubes
  18.             End Get
  19.         End Property
  20.         Private Sub New(ByVal Spig As Single, ByVal Ps As Single)
  21.             Me._Spig = Spig
  22.             Me._Ps = Ps
  23.             _cubes.Add(Spig, Me)
  24.             'IN ALTERNATIVA _cubes.Add(Spig, Ps)
  25.         End Sub
  26.  
  27.         Public Shared Function create(ByVal Spig As Single, ByVal Ps As Single) As cube
  28.             If Spig > 0 And Ps > 0 Then
  29.                 Return New cube(Spig, Ps)
  30.             Else
  31.                 'IGNORANDO LA GESTIONE DEGLI ERRORI
  32.                 Return New cube(1, 1)
  33.             End If
  34.         End Function
  35.  
  36.     End Class
  37.     Sub Main()
  38.        
  39.         Dim A As cube = cube.create(1.0, 2.5)
  40.         Dim C As cube = cube.create(2.0, 2.5)
  41.         Dim E As cube = cube.create(3.0, 3.5)
  42.  
  43.         'NON FUNZIONA
  44.         'Dim H As Hashtable = cube.cubes
  45.         'Console.WriteLine("Cubo A: " & H(1.0).Ps)
  46.  
  47.         Console.ReadKey()
  48.  
  49.         'NON FUNZIONA
  50.         Dim Y As cube = cube.cubes(3.0)
  51.         Console.WriteLine("Cubo E: " & Y.Ps)
  52.  
  53.         'SOLO QUESTA FUNZIONA
  54.         For Each X As DictionaryEntry In cube.cubes
  55.             Dim Z As cube = X.Value
  56.             Console.WriteLine(Z.Spig)
  57.             Console.WriteLine(Z.Ps)
  58.         Next
  59.  
  60.         Console.ReadKey()
  61.  
  62.     End Sub
  63.  
  64. End Module




PM
Avatar
Il Totem (Admin)
Guru^2


Messaggi: 3635
Iscritto: 24/01/2006

Up
0
Down
V
Segnala al moderatore
Postato alle 16:16
Lunedì, 30/08/2010
Ho convertito il tuo codice in C# perchè ora sono su linux e mi manca vbc. Ho riscontrato che il for stampa i valori corretti, ma nel formato sbagliato. Stampa 1, non 1.0. Ciò significa che l'oggetto contenuto nello spazio dedicato _Spig non è un Single, ma piuttosto un Integer. Poiché la chiave di ricerca è un double (3.0 è double, 3.0F single), il match non sussiste. Una possibile causa dell'errore potrebbe risiedere nel fatto che usi Hashtable, ossia una versione a tipizzazione debole del tipo Dictionary. Come avrai già letto, ciò implica che ogni valore e chiave è mappato in una variabile di tipo object tramite boxing, il che potrebbe far perdere al dato immesso la sua propria natura a causa di conversioni implicite. Inoltre, sempre perchè le chiavi sono mappate da objects, quindi oggetti reference, posso presumere che il confronto avvenga per riferimento.
Una soluzione sarebbe quella di usare la versione a tipizzazione forte, Dictionary(Of T, K), con l'ausilio dei generics. Questo è un possibile esempio del perchè le chiavi di tipo floating point siano da evitare (il caso per eccellenza sarebbe l'errore di approssimazione).

PM
Avatar
Marcus65 (Normal User)
Newbie


Messaggi: 10
Iscritto: 30/08/2010

Up
0
Down
V
Segnala al moderatore
Postato alle 7:06
Martedì, 31/08/2010
Ok. Siccome sto studiando (pochissimo: ci metterò 2 anni a finire il tuo corso fra occupazioni di lavoro e bambini) e il programma è di prova, ho provato ad adottare una chiave stringa.
Fnziona tutto: il for, che tuttavia mi sembrava funzionasse (in VB) bene anche prima e anche le ricerche "secche" di un singolo elemento che poi era ciò che mi interessave maggiormente: vedere se le maniere che avevo pensato per richiamare un elemento singolo dell'hashtable funzionavano. Ok, a patto di avere una stringa come chiave.

PM
Avatar
Il Totem (Admin)
Guru^2


Messaggi: 3635
Iscritto: 24/01/2006

Up
0
Down
V
Segnala al moderatore
Postato alle 10:32
Martedì, 31/08/2010
Una chiave stringa nell'hashtable è un classico, ma questo tipo è comunque progettato per accettare un qualsiasi tipo di chiave. Quando arriverai a leggere i generics, potrai approfittarne.

PM
Avatar
Il Totem (Admin)
Guru^2


Messaggi: 3635
Iscritto: 24/01/2006

Up
-2
Down
V
Segnala al moderatore
Postato alle 10:53
Lunedì, 30/08/2010
1) Non è necessario scrivere il costruttore nel primo modo, né è più corretto nel secondo. Entrambi hanno sia pregi che difetti. Il primo ha il vanto di accedere direttamente ai campi privati, senza passare per le proprietà: questo favorisce un'interazione più diretta e veloce con i dati, specialmente nel caso tali proprietà contengano molto codice di controllo. Inoltre, dato che il costruttore è privato e viene richiamato da un metodo factory è ragionevole supporre che suddetto metodo abbia controllato in anticipo il valore dei parametri, verificando che sia coerente, dato che è proprio questa l'utilità dei metodi factory. Il secondo, al contrario, è meno diretto, ma può comunque gestire valori erronei dei parametri, anche se, come già detto, è un'operazione superflua in un metodo factory.

2) E' quello che mi chiedo anche io, perchè non dovrebbe? Tu non hai postato, però, l'output che ottieni richiamando quel codice, o l'eccezione che viene generata, quindi non posso sapere qual è il problema.

PM