Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 15
  1. #1
    Utente di HTML.it L'avatar di pietro09
    Registrato dal
    Jan 2002
    Messaggi
    10,116

    [c#-vb.net] collezione di oggetti univoci

    :master: Semplifico al massimo facendo un esempio minimale.

    Ho una classe, classe1, con due campi, A e B, A di tipo stringa, B di tipo Enum.

    Volevo creare una collezione di oggetti di classe1, ma mettendo solo valori univoci.

    Nella collezione, due oggetti di classe1 sono uguali se hanno la proprietà A identiche, indipendentemente da maiuscolo-minuscolo.

    :master: sono un po' confuso. Mi dareste una mano?
    Pietro

  2. #2
    Utente di HTML.it
    Registrato dal
    Apr 2009
    Messaggi
    970
    Sentendo la parola univoco a me viene in mente solo la parola HashTable.
    Sbagliare è umano, perseverare è diabolico.

  3. #3
    Utente di HTML.it L'avatar di pietro09
    Registrato dal
    Jan 2002
    Messaggi
    10,116
    Originariamente inviato da Pirelli72
    Sentendo la parola univoco a me viene in mente solo la parola HashTable.
    :master: Sì, è vero. Però forse non basta, credo :master:

    :master:
    Pietro

  4. #4
    Utente di HTML.it
    Registrato dal
    Apr 2009
    Messaggi
    970
    Sicuramente non basta ma sarà la base di partenza.
    Sbagliare è umano, perseverare è diabolico.

  5. #5
    Utente di HTML.it L'avatar di pietro09
    Registrato dal
    Jan 2002
    Messaggi
    10,116
    Ci provo, ciao
    Pietro

  6. #6
    Potresti usare la classe HashSet(Of), oppure Dictionary(Of). In ogni caso il problema non sta tanto nel tipo di classe collection che andrai ad usare, ma nel sistema utilizzato dalla classe per capire se due oggetti sono uguali oppure no.
    Se scrivo questo codice:
    codice:
    Dim hs As New HashSet(Of String)
    hs.Add("Ciao")
    hs.Add("Ciao")
    hs.Add("Hello")
    Console.WriteLine(hs.Count)  'ritorna 2
    scopro che la collezione contiene due elementi, "Ciao" e "Hello". Questo perché la classe HashSet ha "scartato" il secondo "Ciao" in quanto già esistente. Se faccio lo stesso esperimento con degli oggetti (e non più con le stringhe) il comportamento purtroppo cambia:
    codice:
    Public Class Class1
        Private _a As String
    
        Public Property A As String
        ....
        End Property
    
        Public Sub New(a As String)
            _a = a
        End Sub
    End Class
    
    Dim hs As New HashSet(Of Class1)
    hs.Add(New Class1("Ciao"))
    hs.Add(New Class1("Ciao"))
    hs.Add(New Class1("Hello"))
    Console.WriteLine(hs.Count)  'ritorna 3
    Il funzionamento è diverso perché, trattandosi di istanze di Class1, la classe HashSet confronta (probabilmente) gli handle in memoria usati per memorizzare i due oggetti: se gli handle sono uguali vuol dire che si tratta dello stesso oggetto, altrimenti si tratta sicuramente di due oggetti diversi. In altre parole HashSet non controlla se i membri dei due oggetti sono uguali tra loro, ma solamente se essi hanno lo stesso handle.
    La soluzione è abbastanza semplice e consiste nel fare l'override di due metodi ereditati dalla classe Object, GetHashCode ed Equals, in questo modo:
    codice:
    Public Class Class1
        Private _a As String
    
        Public Property A As String
        ....
        End Property
    
        Public Sub New(a As String)
            _a = a
        End Sub
    
        Public Overrides Function GetHashCode() As Integer
            Return 0
        End Function
    
        Public Overrides Function Equals(ByVal obj As Object) As Boolean
            Dim c As Class1 = CType(obj, Class1)
            'confronta i membri
            Return (c.A = Me.A)
        End Function
    End Class
    Nell'esempio mi sono limitato ad una sola property (A), ma è evidente che puoi eseguire il confronto tra più proprietà diverse.
    Chi non cerca trova.

  7. #7
    Utente di HTML.it L'avatar di pietro09
    Registrato dal
    Jan 2002
    Messaggi
    10,116
    Ti ringrazio. Mi studio il codice.
    Pietro

  8. #8
    Utente di HTML.it L'avatar di pietro09
    Registrato dal
    Jan 2002
    Messaggi
    10,116
    :master: Ammettendo di non aver fatto pasticci, ho fatto questo esempio :master:
    codice:
    Imports System.Collections
    Imports Microsoft.VisualBasic.FileIO
    Imports System.Collections.Generic
    Imports System.Collections.Specialized
    
    
    Module Module1
    
        Sub Main()
            Dim cs As New Dictionary(Of Classe, Classe)(Classe.EqualityComparer)
            Try
                Dim c As Classe = Nothing
                c = New Classe("a", "a") : cs.Add(c, c)
                c = New Classe("b", "a") : cs.Add(c, c)
                c = New Classe("B", "x") : cs.Add(c, c) 'non posso farlo
    
    
            Catch ex As Exception
                Console.WriteLine(ex.Message)
            End Try
        End Sub
    
    End Module
    
    Public Class Classe
        Public A As String
        Public B As String
    
        Public Sub New(ByVal a As String, ByVal b As String)
            Me.A = a
            Me.B = b
        End Sub
    
    
        Public Class _EqualityComparer
            Implements IEqualityComparer(Of Classe)
    
            Public Function Equals1(ByVal x As Classe, ByVal y As Classe) As Boolean Implements System.Collections.Generic.IEqualityComparer(Of Classe).Equals
                Return String.Equals(x.A, y.A, StringComparison.OrdinalIgnoreCase)
            End Function
    
            Public Function GetHashCode1(ByVal obj As Classe) As Integer Implements System.Collections.Generic.IEqualityComparer(Of Classe).GetHashCode
                Return obj.A.ToLower.GetHashCode
            End Function
        End Class
    
        Public Shared ReadOnly EqualityComparer As New _EqualityComparer()
    
    
    End Class
    Pietro

  9. #9
    Utente di HTML.it L'avatar di pietro09
    Registrato dal
    Jan 2002
    Messaggi
    10,116
    :master: Questo mi pare un poco meglio
    anche se non sono ancora contento.

    cs.Add(c, c) forse è meglio trasformarlo in cs.add(c), dato che sono uguali
    forse si può fare con una List(of classe) utilizzando un altro aproccio

    Comunque, grazie ancora dell'aiuto






    codice:
    Imports System.Collections
    Imports Microsoft.VisualBasic.FileIO
    Imports System.Collections.Generic
    Imports System.Collections.Specialized
    
    
    Module Module1
    
        Sub Main()
            'Dim cs As New Dictionary(Of Classe, Classe)(Classe.EqualityComparer)
            Dim cs As New Classi()
            Try
                Dim c As Classe = Nothing
                c = New Classe("a", "a") : cs.Add(c, c)
                c = New Classe("b", "a") : cs.Add(c, c)
                c = New Classe("B", "x") : cs.Add(c, c) 'non posso farlo
    
    
            Catch ex As Exception
                Console.WriteLine(ex.Message)
            End Try
        End Sub
    
    End Module
    
    Public Class Classe
        Public A As String
        Public B As String
    
        Public Sub New(ByVal a As String, ByVal b As String)
            Me.A = a
            Me.B = b
        End Sub
    
    
    End Class
    
    
    Public Class Classi
        Inherits Dictionary(Of Classe, Classe)
    
        Public Sub New()
            MyBase.New(New EqualityComparer())
        End Sub
    
        Private Class EqualityComparer
            Implements IEqualityComparer(Of Classe)
    
            Public Function Equals1(ByVal x As Classe, ByVal y As Classe) As Boolean Implements System.Collections.Generic.IEqualityComparer(Of Classe).Equals
                Return String.Equals(x.A, y.A, StringComparison.OrdinalIgnoreCase)
            End Function
    
            Public Function GetHashCode1(ByVal obj As Classe) As Integer Implements System.Collections.Generic.IEqualityComparer(Of Classe).GetHashCode
                Return obj.A.ToLower.GetHashCode
            End Function
        End Class
    
    
    End Class
    Pietro

  10. #10
    Hai guardato la classe HashSet? Ha pure un costruttore che richiede una classe che implementa IEqualityComparer
    Chi non cerca trova.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.