1

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
Ivan Chaer
  • 6,980
  • 1
  • 38
  • 48
Happypig375
  • 1,022
  • 1
  • 12
  • 32
  • You can install .NET 4.6 on Windows 7, do you have any restriction therefore you must use the bundled framework? – Stefano d'Antonio Jul 05 '16 at 10:41
  • No admin account to install for me to use... – Happypig375 Jul 05 '16 at 10:45
  • *"I am using .NET 3.5 to maintain compatibility with Win7"* - you do know that you can install the .NET framework 4.0 on anything back to windows XP don't you? https://msdn.microsoft.com/en-us/library/8z6watww(v=vs.100).aspx – Matt Wilko Jul 05 '16 at 12:54

1 Answers1

2

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.

Stefano d'Antonio
  • 5,874
  • 3
  • 32
  • 45
  • *Be aware that the framework already has an IReadOnlyDictionary and a ReadOnlyDictionary so you might not need to implement a custom one.* Added a description for why I did not use the .NET class. – Happypig375 Jul 05 '16 at 10:38