You might be interested in seeing what happens if you create a class to
That was actually the first thing I tried,
but I gave up when I discovered that I use the ContainsValue method on the
dictionary
If dic.ContainsValue(False) Then <do something>
and I didn't want to figure out how to either implement some arcane
interface or write my own "search through the darned thing" routine to get
that to work.
Ok, I knew digging this simple bit of knowledge out of the documentation was
going to be a pain, and I was right. You'd think that now that VS is fully
mature the documentation would contain more and better examples baked right
into the topics that F1 help most easily gets you to. Anyway, after a
little spelunking I fgured out that a class T needs to implement the
IEquatable(Of T) interface in order to get Dictionary(Of T).ContainsValue to
work. Why the documentation for Dictionary(Of T).ContainsValue doesn't say
that in so many words is beyond me!
After all that, it turns out that executing ContainsValue on a Dictionary(Of
Int32, Boolean) is about 3 times faster than doing the same thing on a
Dictionary(Of Int32, MyWrapperClass).
So, to summarize:
1. Modifying all of the values in a Dictionary whose values are value types
is surprising difficult.
2. The fastest way to do it seems to be to make a copy of the keys, and use
that copy to iterate through the Dictionary.
3. Performing the same operation on a Dictionary whose values are reference
types is straightforward and much faster, but requires extra claptrap to
declare the reference type.
4. In order to get Dictinoary(T).ContainsValue to work with values that are
reference types requires that the reference type implement IEquatable. As
one would expect, ContainsValue is much faster operating on Boolean values
compared with objects that wrap Boolean values.
----- Code (requires 5 buttons and one label) -----
Public Class Form1
Dim m_booleanDictionary As New Dictionary(Of Int32, Boolean)
Private Class BoolWrapper
Implements IEquatable(Of BoolWrapper)
Public Value As Boolean
Public Sub New(ByVal value As Boolean)
Me.Value = value
End Sub
Public Function Equals1( _
ByVal other As BoolWrapper) As Boolean Implements System.IEquatable(Of
BoolWrapper).Equals
Return Me.Value = other.Value
End Function
End Class
Dim m_classDictionary As New Dictionary(Of Int32, BoolWrapper)
Private Sub Form1_Load( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
For i As Int32 = 1 To 1000
Dim key As Int32 = CInt(Rnd() * 10000)
m_booleanDictionary(key) = True
m_classDictionary(key) = New BoolWrapper(True)
Next
End Sub
Private Sub Button1_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim t1 As DateTime = Now
For i As Int32 = 1 To 10000
' Kerry's algorithm
Dim keys(m_booleanDictionary.Count - 1) As Int32
m_booleanDictionary.Keys.CopyTo(keys, 0)
For Each key As Int32 In keys
m_booleanDictionary(key) = False
Next
Next
Dim t2 As Date = Now
Label1.Text = (t2 - t1).TotalMilliseconds.ToString
End Sub
Private Sub Button2_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
Dim t1 As DateTime = Now
For i As Int32 = 1 To 10000
' Bob's algorithm
Dim newDic As New Dictionary(Of Int32, Boolean)
For Each kvp As KeyValuePair(Of Int32, Boolean) In m_booleanDictionary
newDic(kvp.Key) = False
Next
m_booleanDictionary = newDic
Next
Dim t2 As Date = Now
Label1.Text = (t2 - t1).TotalMilliseconds.ToString
End Sub
Private Sub Button3_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button3.Click
Dim t1 As DateTime = Now
For i As Int32 = 1 To 10000
For Each t As BoolWrapper In m_classDictionary.Values
t.Value = False
Next
Next
Dim t2 As Date = Now
Label1.Text = (t2 - t1).TotalMilliseconds.ToString
End Sub
Private Sub Button4_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button4.Click
' Button 4 tests ContainsValue time for Dictionary of Booleans
Dim t1 As DateTime = Now
For i As Int32 = 1 To 10000
m_booleanDictionary.ContainsValue(True)
m_booleanDictionary.ContainsValue(False)
Next
Dim t2 As Date = Now
Label1.Text = (t2 - t1).TotalMilliseconds.ToString
End Sub
Private Sub Button5_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button5.Click
' Button 5 tests ContainsValue time for Dictionary of objects
' that implement IEquatable
Dim t1 As DateTime = Now
Dim falseWrapper As New BoolWrapper(False)
Dim trueWrapper As New BoolWrapper(True)
For i As Int32 = 1 To 10000
m_classDictionary.ContainsValue(trueWrapper)
m_classDictionary.ContainsValue(falseWrapper)
Next
Dim t2 As Date = Now
Label1.Text = (t2 - t1).TotalMilliseconds.ToString
End Sub
End Class