Visual Basic 2012 Voorbeelden
   

visual basic 2012 broncode voorbeelden

Blijf op de hoogte van de recente aanpassingen op vbvoorbeelden!

Microsoft Visual Studio 2012Microsoft Developers Network - Visual BasicMicrosoft .NET Framework

22.16. Dictionaries en Value Types

Print Email Deel op Twitter Deel op Facebook

Dit artikel is gepubliceerd op maandag 15 oktober 2012 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.

Veronderstel volgende klasse Counter.  Objecten van deze klasse hebben een Value en StepValue.  Bij het verhogen (Raise) en verlagen ( Lower) wordt de Value verhoogt of verlaagt met de StepValue.

Twee Counter objecten worden als logisch gelijk beschouwd indien ze dezelfde Value en StepValue toestand hebben, de Equals implementatie gaat dit hier dan ook na.
Omdat Equals wordt geherdefinieerd, moeten we ook GetHasCode herdefiniëren en zorgen dat objecten die als logisch gelijk worden beschouwd dan ook dezelfde hash code opleveren.  Dit garandeert dus ondermeer dat objecten van het type Counter als key voor een dictionary kunnen worden gebruikt.
Visual Basic 2012 Broncode - Codevoorbeeld 560
Namespace Example1
    Class Counter
        Public Sub New(ByVal value As Integer)
            _Value = value
        End Sub
        Private _Value As Integer
        Public ReadOnly Property Value() As Integer
            Get
                Value = _Value
            End Get
        End Property
        Public Property StepValue As Integer
        Public Sub Raise()
            _Value += StepValue
        End Sub
        Public Sub Lower()
            _Value -= StepValue
        End Sub
        Public Overrides Function Equals(ByVal obj As Object) As Boolean
            If obj IsNot Nothing AndAlso TypeOf obj Is Counter Then
                Dim other As Counter = DirectCast(obj, Counter)
                Equals = (Me.Value = other.Value AndAlso _
                          Me.StepValue = other.StepValue)
            End If
        End Function
        Public Overrides Function GetHashCode() As Integer
            GetHashCode = Value Xor StepValue
        End Function
    End Class
End Namespace
Gebruiken we Counter nu effectief als keytype voor een dictionary dan levert dit ons ook het verwachte en gewenste resultaat :
Visual Basic 2012 Broncode - Codevoorbeeld 561
Namespace Example1
    Class Client
        Public Shared Sub Main()
            Dim counter1 As New Counter(1) With {.StepValue = 5}
            Dim counter2 As New Counter(1) With {.StepValue = 5}
            Dim counter3 As New Counter(1) With {.StepValue = 10}
            '
            Dim hashtable1 As New Hashtable
            hashtable1.Add(counter1, "value")
            '
            Console.WriteLine(hashtable1.Item(counter1).ToString()) ' value
            Console.WriteLine(hashtable1.Item(counter2).ToString()) ' value
            Console.WriteLine(hashtable1.Item(counter3) Is Nothing) ' True
            '
            Console.ReadLine()
        End Sub
    End Class
End Namespace
Console Application Output
value
value
True
Counter counter2, in tegenstelling tot counter3, heeft wel dezelfde Value en StepValue als counter1.  Hierdoor worden counter1 en counter2 als logisch gelijk beschouwd, en zal de Hashtable bij het zoeken naar het element met key counter2 ook "value" opleveren.

Maken we van Counter een value type (Structure) dan hoeven we zelfs Equals en GetHashCode niet te overschrijven :
Visual Basic 2012 Broncode - Codevoorbeeld 562
Namespace Example2
    Structure Counter
        Public Sub New(ByVal value As Integer)
            _Value = value
        End Sub
        Private _Value As Integer
        Public ReadOnly Property Value() As Integer
            Get
                Value = _Value
            End Get
        End Property
        Public Property StepValue As Integer
        Public Sub Raise()
            _Value += StepValue
        End Sub
        Public Sub Lower()
            _Value -= StepValue
        End Sub
    End Structure
    Class Client
        Public Shared Sub Main()
            Dim counter1 As New Counter(1) With {.StepValue = 5}
            Dim counter2 As New Counter(1) With {.StepValue = 5}
            Dim counter3 As New Counter(1) With {.StepValue = 10}
            '
            Dim hashtable1 As New Hashtable
            hashtable1.Add(counter1, "value")
            '
            Console.WriteLine(hashtable1.Item(counter1).ToString()) ' value
            Console.WriteLine(hashtable1.Item(counter2).ToString()) ' value
            Console.WriteLine(hashtable1.Item(counter3) Is Nothing) ' True
            '
            Console.ReadLine()
        End Sub
    End Class
End Namespace
Console Application Output
value
value
True
Logische gelijkheid wordt bij value types instanties by default gebaseerd op de volledige toestand van de instantie.  Met volledige toestand wordt bedoeld de verzameling van alle veldwaardes.
By default wordt ook de hash code voor value type instanties op alle velden gebaseerd.

Voor meer details over logisch gelijkheid bij value type en versus logische gelijkheid bij reference types zie het desbetreffende topic.

Het is echter niet aan te raden al te veel te vertrouwen op de overgeërfde implementatie van Equals en GetHashCode.  Deze overgeërfde implementatie van GetHashCode bijvoorbeeld zal doorgaans wel een unieke hash code opleveren voor elk logisch uniek object, maar dit wordt in principe niet gegarandeerd.  Ook wordt niet gegarandeerd dat verschillende versies van het .NET Framework dezelfde hash code opleveren voor objecten met dezelfde toestand.  Dit kan bijvoorbeeld tot problemen leiden indien verschillende componenten/assemblies in een applicatie op verschillende versies van het Framework werken.
Het is bijkomend ook zo dat de overgeërfde Equals implementatie, afhankelijk van de complexiteit van het type, een vrij grote performance overhead hebben.  Het nagaan van gelijkheid tussen twee value type instanties met die overgeërfde implementatie kan dus vrij lang duren.

Conclusie is dat het in principe voor value types altijd aan te raden deze Equals en GetHashCode zelf te definiëren.

Hier in dit geval zouden we dat kunnen doen door volgende methods toe te voegen :
Visual Basic 2012 Broncode - Codevoorbeeld 563
Namespace Example2
    Partial Structure Counter
        Public Overrides Function Equals(ByVal obj As Object) As Boolean
            If obj IsNot Nothing AndAlso TypeOf obj Is Counter Then
                Dim other As Counter = DirectCast(obj, Counter)
                Equals = (Me.Value = other.Value AndAlso _
                          Me.StepValue = other.StepValue)
            End If
        End Function
        Public Overrides Function GetHashCode() As Integer
            GetHashCode = Value Xor StepValue
        End Function
    End Structure
End Namespace
Indien we logische gelijkheid tussen twee Counters enkel willen baseren op Value en niet meer op Value en StepValue, krijgen we niet meer het gewenste resultaat.

In dat geval moeten we sowieso wel Equals en GetHashCode overschrijven :
Visual Basic 2012 Broncode - Codevoorbeeld 564
Namespace Example3
    Structure Counter
        Public Sub New(ByVal value As Integer)
            _Value = value
        End Sub
        Private _Value As Integer
        Public ReadOnly Property Value() As Integer
            Get
                Value = _Value
            End Get
        End Property
        Public Property StepValue As Integer
        Public Sub Raise()
            _Value += StepValue
        End Sub
        Public Sub Lower()
            _Value -= StepValue
        End Sub
        Public Overrides Function Equals(ByVal obj As Object) As Boolean
            If obj IsNot Nothing AndAlso TypeOf obj Is Counter Then
                Dim other As Counter = DirectCast(obj, Counter)
                Equals = (Me.Value = other.Value)
            End If
        End Function
        Public Overrides Function GetHashCode() As Integer
            GetHashCode = Value
        End Function
    End Structure
    Class Client
        Public Shared Sub Main()
            Dim counter1 As New Counter(1) With {.StepValue = 5}
            Dim counter2 As New Counter(1) With {.StepValue = 5}
            Dim counter3 As New Counter(1) With {.StepValue = 10}
            '
            Dim hashtable1 As New Hashtable
            hashtable1.Add(counter1, "value")
            '
            Console.WriteLine(hashtable1.Item(counter1).ToString()) ' value
            Console.WriteLine(hashtable1.Item(counter2).ToString()) ' value
            Console.WriteLine(hashtable1.Item(counter3).ToString()) ' value
            '
            Console.ReadLine()
        End Sub
    End Class
End Namespace
Console Application Output
value
value
value

Dit artikel is gepubliceerd op maandag 15 oktober 2012 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.