写一个字典(“条目”).clone()

时间:2017-03-27 16:39:08

标签: vb.net dictionary

我有一个名为ReDictionary

的班级

编辑:我的班级声明

Public Class ReDictionary(Of TKey, TValue) Inherits Dictionary(Of TKey, TValue)

为我的词典目的提供了一些小的增强功能。

' Wraps TryGetValue
Public Function ValueOr(key, OnNoValue)
    dim TossBool = Me.TryGetValue(key, TossObj)
    If TossBool Then
        Return TossObj
    Else
        Return OnNoValue
    End If
End Function

我正在尝试编写一个.Clone()方法(浅层)作为课程的一部分。

我尝试过使用TopLevelDictionary.clone(src,dest)语法的函数和使用TopLevelDict("Entry").Clone(src)语法的 sub

Public Sub Clone(srcKey As TKey, destKey As TValue) As ReDictionary(Of object, object)
    Dim newbook As New ReDictionary(Of Object, Object)
    For Each kvp As KeyValuePair(Of Object, Object) In Me(srcKey)
        newbook(kvp.Key) = kvp.Value.ToString()
    Next
    Me(destKey) = newbook
End Sub

这几乎是一个准代码。我可能尝试了TKey/TValueObject/Object的每个组合,甚至是我想要克隆的两个字典的String/String的具体情况。我也尝试过不指定参数/返回类型

我通常得到的错误是Cannot Convert ReDictionary(...) to ReDictionary(...),例如当函数临时ReDictionary为(Object, Object)且源ReDictionary为(String, String)时。

我想避免制作我的公共字典(Object, Object),因为它在内存上似乎很浪费。

我的两个词典填充在表单加载的相同函数中。一个是公共的,另一个是函数的本地,但是传递值(通过语言选择的描述)全局字典。

我已经意识到我可以很容易地编写一个克隆函数(不是ReDictionary的一部分,它使用Dict(NewEntry) = CloneEntry(Dict("Entry")之类的语法。之前我曾经尝试克隆对象之前有类似的东西。公共字典。

Private Function CloneObj(key) As ReDictionary(Of String, String)
    Dim inObj = New ReDictionary(Of String, String)
    For Each kvp As KeyValuePair(Of String, String) In pLib(key)
        inObj(kvp.Key) = pLib(key)(kvp.Key)
    Next
    Return inObj
End Function

虽然我尝试放松对象类型时可能会遇到冲突。

  • 全球词典是Dictionary(String) of Dictionaries(String) of Strings
  • 本地词典是Dictionary(String) of cTranslations(class) with String properties

此时,有两个功能可以做到,但如果可能,我会更加坚定。

更新:这是我目前正在尝试使用的版本

Public Class ReDictionary(Of TKey, TValue)
    Inherits Dictionary(Of TKey, TValue)
    Public Function Clone(srcKey As Object) As ReDictionary(Of TKey, TValue)
        Dim inObj As New ReDictionary(Of TKey, TValue)
        For Each kvp As KeyValuePair(Of TKey, TValue) In Me
            inObj(kvp.Key) = kvp.Value
        Next
        Return inObj
    End Function
End Class

这是该语法的示例用法。

Dim Films As New ReDictionary(Of String, ReDictionary(Of String, String)
Films("Edge of Tomorrow") = New ReDictionary(Of String, String)
Films("Edge of Tomorrow")("Description") = "Tom Crues goes to war on Groundhog's Day"
Films("Live, Die, Repeat") = Films.Clone("Edge of Tomorrow")

Films("Birdman") = New ReDictionary(Of String, String)
Films("Birdman")("Description") = "Michael Keyton, who played a superhero 20 years ago, plays an actor who also did"
Films("The Unexpected Virtue of Ignorance") = Films.Clone("Birdman")

我实际上更改了某些克隆项的某些属性,这就是为什么我需要克隆而不是只有一个条目是对兄弟条目的引用。

函数本身实际上并没有导致任何错误,但是当我尝试使用它时,我得到(直接从调试器复制,只是缩进以便它易于阅读):

错误很明显

Value of type 'ReDictionary(Of String, ReDictionary(Of String, String))' cannot be converted to 'ReDictionary(Of String, String)

如果我将In Me更改为In Me(srckey),我会

Expression of type TValue which is not a collection type

将srcKey的输入更改为TValueTKey也会导致错误,同时删除srckey的输入。

2 个答案:

答案 0 :(得分:1)

首先,我想指出你应该制作对象而不是使用字典,但我离题了。

那么,为什么它不起作用呢。

首先,让我们看一下Clone函数

Public Class ReDictionary(Of TKey, TValue)
    Inherits Dictionary(Of TKey, TValue)
    Public Function Clone(srcKey As Object) As ReDictionary(Of TKey, TValue)
        Dim inObj As New ReDictionary(Of TKey, TValue)
        For Each kvp As KeyValuePair(Of TKey, TValue) In Me
            inObj(kvp.Key) = kvp.Value
        Next
        Return inObj
    End Function
End Class

注意永远不会使用srcKey。因此,此函数返回您正在调用它的ReDictionary的克隆, ReDictionary中包含的TopLevel(srcKey)

接下来,让我们看看你是如何使用它的。

Dim Films As New ReDictionary(Of String, ReDictionary(Of String, String)
Films("Edge of Tomorrow") = New ReDictionary(Of String, String)
Films("Edge of Tomorrow")("Description") = "Tom Crues goes to war on Groundhog's Day"
Films("Live, Die, Repeat") = Films.Clone("Edge of Tomorrow")

如上所述,Films.Clone将返回与调用ReDictionary相同类型的ReDictionary,这意味着您正在尝试将ReDictionary(Of String, ReDictionary(Of String, String)分配给Films("Live, Die, Repeat") },类型为ReDictionary(Of String, String)

这两种显然是不同的类型,因此你无法完成这项任务。

所以需要修复的是:

Clone方法

我建议您删除srcKey参数并使用此方法克隆您正在调用它的对象(这就是它已经在做的事情)

用法

现在,因为Clone将克隆您正在调用它的字典,所以您可以执行以下操作:

Dim Films As New ReDictionary(Of String, ReDictionary(Of String, String)
Films("Edge of Tomorrow") = New ReDictionary(Of String, String)
Films("Edge of Tomorrow")("Description") = "Tom Crues goes to war on Groundhog's Day"
Films("Live, Die, Repeat") = Films("Edge of Tomorrow").Clone()

答案 1 :(得分:0)

正如Joe在评论中所说的那样,扩展方法最终得到了最好的效果,但是没有看到try/catchif/else之外的普遍打字方式。

我找到了Dim Args as type() = SourceDict.GetType().GetGenericArguments(),但由于我无法将变量用于对象类型,例如Dim inObject As New Dictionary(Of Args(0), Args(1)),因此似乎需要重复。

离开这里,以防万一

Public Module DictionaryExtensions '(Of Tkey, TValue)
    <Extension()>
    Public Function CloneDict(ByVal SourceDict As Object,
                       ByVal SourceKey As String) As IDictionary
        Try
            Dim inObject As New Dictionary(Of String, String)
            For Each kvp As KeyValuePair(Of String, String) In SourceDict(SourceKey)
                inObject(kvp.Key) = SourceDict(SourceKey)(kvp.Key)
            Next
            Return inObject
        Catch
            Dim inObject As New Dictionary(Of String, Translation)
            For Each kvp As KeyValuePair(Of String, Translation) In SourceDict(SourceKey)
                inObject(kvp.Key) = SourceDict(SourceKey)(kvp.Key)
            Next
            Return inObject
        End Try
    End Function

    <Extension()>
    Public Function ValueOr(ByVal SourceObject As Object,
                       ByVal Key As Object,
                       Optional ByVal onnovalue As Boolean = False)
        Dim TossBool as Boolean = SourceObject.TryGetValue(Key, TossObj)
        If TossBool Then
            Return TossObj
        Else
            Return onnovalue
        End If
    End Function

    <Extension()>
    Public Function ValueOr(ByVal SourceObject As Object,
                       ByVal Key As Object,
                       ByVal onnovalue As Object)
        Dim TossBool as Boolean = SourceObject.TryGetValue(Key, TossObj)
        If TossBool Then
            Return TossObj
        Else
            Return onnovalue
        End If
    End Function
End Module