Happypig375 Happypig375 - 5 months ago 75
Vb.net Question

Unable to initialize a dictionary with a an array variable

How can I convert

{{"variable", "default value"},{"integer","123"}}
as in

Public PredefinedVariables As New ReadOnlyDictionary(Of String, String) ({{"variable", "default value"},{"integer","123"}})


to
IDictionary(Of String, String)
?

(Maybe you should read the implementation of
ReadOnlyDictionary
below first)

Sub New(array As Array)
_dictionary = New Dictionary(Of TKey, TValue) From array
End Sub


won't work for me because of
End of statement expected
at
From array
.

So, I think the only methods are to convert the array to an
IDictionary
, rewrite the array to
KeyValuePair()
to initalize
_dictionary
, or declare a class that implements
IDictionary
and use the array to initialize it. However, the first two seems impossible and I have not found a class that fits in the third condition.

Class ReadOnlyDictionary (I am using .NET 3.5 to maintain compatibility with Win7. The .NET ReadOnlyDictionary is only avaliable in .NET 4.0+):

Public Class ReadOnlyDictionary(Of TKey, TValue)
Inherits ReadOnlyCollectionBase
Implements IDictionary(Of TKey, TValue),
IEmptyInterface, 'IDictionary, IReadOnlyDictionary(Of TKey, TValue),ISerializable, IDeserializationCallback
ICollection(Of KeyValuePair(Of TKey, TValue)), IEnumerable(Of KeyValuePair(Of TKey, TValue)), IEnumerable
Private ReadOnly _dictionary As IDictionary(Of TKey, TValue)

Public Sub New()
_dictionary = New Dictionary(Of TKey, TValue)()
End Sub

Public Sub New(dictionary As IDictionary(Of TKey, TValue))
_dictionary = New Dictionary(Of TKey, TValue)(dictionary)
End Sub

Public Sub New(dictionary As IDictionary(Of TKey, TValue), comparer As IComparer(Of TKey))
_dictionary = New Dictionary(Of TKey, TValue)(dictionary, comparer)
End Sub

#Region "IDictionary<TKey,TValue> Members"

Private Sub IDictionary_Add(key As TKey, value As TValue) Implements IDictionary(Of TKey, TValue).Add
Throw ReadOnlyException()
End Sub

Public Function ContainsKey(key As TKey) As Boolean Implements IDictionary(Of TKey, TValue).ContainsKey
Return _dictionary.ContainsKey(key)
End Function

Public ReadOnly Property Keys() As ICollection(Of TKey) Implements IDictionary(Of TKey, TValue).Keys
Get
Return _dictionary.Keys
End Get
End Property

Private Function IDictionary_Remove(key As TKey) As Boolean Implements IDictionary(Of TKey, TValue).Remove
Throw ReadOnlyException()
End Function

Public Function TryGetValue(key As TKey, ByRef value As TValue) As Boolean Implements IDictionary(Of TKey, TValue).TryGetValue
Return _dictionary.TryGetValue(key, value)
End Function

Public ReadOnly Property Values() As ICollection(Of TValue) Implements IDictionary(Of TKey, TValue).Values
Get
Return _dictionary.Values
End Get
End Property

Public ReadOnly Property Item(key As TKey) As TValue
Get
Return _dictionary(key)
End Get
End Property

Default Public Property IDictionary_Item(key As TKey) As TValue Implements IDictionary(Of TKey, TValue).Item
Get
Return Me(key)
End Get
Set
Throw ReadOnlyException()
End Set
End Property

#End Region

#Region "ICollection<KeyValuePair<TKey,TValue>> Members"

Private Sub ICollection_Add(item As KeyValuePair(Of TKey, TValue)) Implements ICollection(Of KeyValuePair(Of TKey, TValue)).Add
Throw ReadOnlyException()
End Sub

Private Sub ICollection_Clear() Implements ICollection(Of KeyValuePair(Of TKey, TValue)).Clear
Throw ReadOnlyException()
End Sub

Public Function Contains(item As KeyValuePair(Of TKey, TValue)) As Boolean Implements ICollection(Of KeyValuePair(Of TKey, TValue)).Contains
Return _dictionary.Contains(item)
End Function

Public Sub CopyTo(array As KeyValuePair(Of TKey, TValue)(), arrayIndex As Integer) Implements ICollection(Of KeyValuePair(Of TKey, TValue)).CopyTo
_dictionary.CopyTo(array, arrayIndex)
End Sub

Public Overrides ReadOnly Property Count() As Integer Implements ICollection(Of KeyValuePair(Of TKey, TValue)).Count
Get
Return _dictionary.Count
End Get
End Property

Public ReadOnly Property IsReadOnly() As Boolean Implements ICollection(Of KeyValuePair(Of TKey, TValue)).IsReadOnly
Get
Return True
End Get
End Property

Private Function ICollection_Remove(item As KeyValuePair(Of TKey, TValue)) As Boolean Implements ICollection(Of KeyValuePair(Of TKey, TValue)).Remove
Throw ReadOnlyException()
End Function

#End Region

#Region "IEnumerable<KeyValuePair<TKey,TValue>> Members"

Public Function GetEnumerator() As IEnumerator(Of KeyValuePair(Of TKey, TValue)) Implements IEnumerable(Of KeyValuePair(Of TKey, TValue)).GetEnumerator
Return _dictionary.GetEnumerator()
End Function

#End Region

#Region "IEnumerable Members"

Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Return GetEnumerator()
End Function

#End Region

Private Shared Function ReadOnlyException() As Exception
Return New NotSupportedException("This dictionary is read-only")
End Function

End Class

Interface IEmptyInterface

End Interface


A few changes to Uno's answer:



Public Sub New(Key As TKey, Value As TValue)
Me.New
_dictionary.Add(Key, Value)
End Sub

Public Sub New(KeyValuePairs As KeyValuePair(Of TKey, TValue)())
Me.New
_dictionary = KeyValuePairs.ToDictionary(Function(x) x.Key, Function(x) x.Value)
End Sub

Uno Uno
Answer

If I understood your question, you would like to initialize a custom Dictionary with the following syntax:

Public Value As New ReadOnlyDictionary(Of String, String) From {{"variable", "default value"},{"integer","123"}}

To do so, if you have VB 14.0, you can just add the Add method to your custom implementation:

Public Sub Add(key As TKey, value As TValue)
     ' Implementation.
End Sub

Be aware that the framework already has an IReadOnlyDictionary and a ReadOnlyDictionary so you might not need to implement a custom one.

Unfortunately, the Add method must be present so it will make it less "ReadOnly" unless you implement some runtime check. The From is just syntactic sugar so it's exactly the equivalent of newing the dictionary up ad adding the values. The only alternative is to pass the values to the constructor.