Oppure

Loading
30/08/10 5:16
Marcus65
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 30/08/10 8:55
aaa
30/08/10 8:53
Il Totem
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.
aaa
30/08/10 13:28
Marcus65
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 ?

Module Module1
    Class cube
        Private _Spig, _Ps As Single
        Private Shared _cubes As New Hashtable
        ReadOnly Property Spig() As Single
            Get
                Return _Spig
            End Get
        End Property
        ReadOnly Property Ps() As Single
            Get
                Return _Ps
            End Get
        End Property
        Shared ReadOnly Property cubes() As Hashtable
            Get
                Return _cubes
            End Get
        End Property
        Private Sub New(ByVal Spig As Single, ByVal Ps As Single)
            Me._Spig = Spig
            Me._Ps = Ps
            _cubes.Add(Spig, Me)
            'IN ALTERNATIVA _cubes.Add(Spig, Ps)
        End Sub

        Public Shared Function create(ByVal Spig As Single, ByVal Ps As Single) As cube
            If Spig > 0 And Ps > 0 Then
                Return New cube(Spig, Ps)
            Else
                'IGNORANDO LA GESTIONE DEGLI ERRORI
                Return New cube(1, 1)
            End If
        End Function

    End Class
    Sub Main()
        
        Dim A As cube = cube.create(1.0, 2.5)
        Dim C As cube = cube.create(2.0, 2.5)
        Dim E As cube = cube.create(3.0, 3.5)

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

        Console.ReadKey()

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

        'SOLO QUESTA FUNZIONA
        For Each X As DictionaryEntry In cube.cubes
            Dim Z As cube = X.Value
            Console.WriteLine(Z.Spig)
            Console.WriteLine(Z.Ps)
        Next

        Console.ReadKey()

    End Sub

End Module


aaa
30/08/10 14:16
Il Totem
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).
aaa
31/08/10 5:06
Marcus65
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.
aaa
31/08/10 8:32
Il Totem
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.
aaa