为什么必须显式声明嵌套类型?

时间:2016-06-09 15:44:16

标签: c# dictionary initialization c#-6.0

我认为这是我第一次使用新的C#6字典初始化功能,我需要一个如下所示的嵌套结构:

        var map = new Dictionary<string, Dictionary<string, object>>()
        {
            ["WNodeScramblingResetZone_Unlock"] = 
            {
                ["updater"] ="pinco",
                ["rdlev"] = 55
            },
            ["WNodeScramblingResetZone_NewPwd"] = 
            {
                ["updater"] ="pallo",
                ["wrlev"] = 75,
                ["is_online"] = true
            }
        };

这种语法似乎很好:没有编译错误。但是,当程序启动时,我在输出窗口中看到一些“KeyNotFoundException”错误,并且应用程序不起作用。

顺便说一句,如果我明确声明了嵌套类型实例化,那么一切都运行正常。

        var map = new Dictionary<string, Dictionary<string, object>>()
        {
            ["WNodeScramblingResetZone_Unlock"] = new Dictionary<string, object>()
            {
                ["updater"] ="pinco",
                ["rdlev"] = 55
            },
            ["WNodeScramblingResetZone_NewPwd"] = new Dictionary<string, object>()
            {
                ["updater"] ="pallo",
                ["wrlev"] = 75,
                ["is_online"] = true
            }
        };

这是一个限制,一个错误,还是有一个具体的理由来定义它?

2 个答案:

答案 0 :(得分:3)

当你编写这样的代码时:

var map = new Dictionary<string, Dictionary<string, object>>()
{
    ["WNodeScramblingResetZone_Unlock"] = 
    {
        ["updater"] ="pinco"
    }
};

它被编译成相当于:

var map = new Dictionary<string, Dictionary<string, object>>()
map["WNodeScramblingResetZone_Unlock"]["updater"] = "pinco";

它不会创建您没有明确指定的任何实例。

这是 可以工作的代码(这就是为什么它被允许)为某些类似字典的类,它为不存在的键返回空集合,但是确实导致KeyNotFoundException的{​​{1}}。

另一方面,这段代码:

Dictionary

编译为:

var map = new Dictionary<string, Dictionary<string, object>>()
{
    ["WNodeScramblingResetZone_Unlock"] = new Dictionary<string, object>()
    {
        ["updater"] ="pinco"
    }
};

正如您所看到的,这会使用新实例(而不是之前版本中的getter)调用var map = new Dictionary<string, Dictionary<string, object>>(); var tmp = new Dictionary<string, object>(); tmp["updater"] = "pinco"; map["WNodeScramblingResetZone_Unlock"] = tmp; setter ,这就是它工作的原因。

答案 1 :(得分:1)

我使用http://tryroslyn.azurewebsites.net/将这个C#代码翻译成VB.NET:

Public Class Program
    Public Shared Sub Main()
        Dim expr_06 As Dictionary(Of String, Dictionary(Of String, Object)) = New Dictionary(Of String, Dictionary(Of String, Object))()
        expr_06("x")("updater") = "pinco"
        expr_06("x")("rdlev") = 55
        expr_06("y")("updater") = "pallo"
        expr_06("y")("wrlev") = 75
        expr_06("y")("is_online") = True
    End Sub
End Class

它清楚地表明,新的词典不是仅通过密钥访问的。新的[key] = value语法编译为dictionary[key] = value,而不是编译为{key, value}的旧版dictionary.Add(key, value)

我认为这是一个功能,编译器不知道您需要什么类型的IDictionary,因此您必须提供具体的类型。您还可以使用一些动态集合,在第一次访问时自动创建子代码,此代码可以使用。正如您可能看到的那样,编译器让您可以自由地执行您想要的操作而牺牲程序的详细程度。

编辑:我写了一点冗长的blog post about initializers,提供了更深入的解释

相关问题