为什么必须显式声明嵌套类型?
Why the nested type must be explicitly declared?
我认为这是我第一次使用新的 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
}
};
这个语法看起来不错:没有编译错误。但是,当程序启动时,我在输出 window 中看到几个 "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
}
};
这是限制、错误,还是有具体的理由来定义它?
我使用 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
所以你必须提供 concrete 类型。您还可以使用一些动态集合,在第一次访问时自动创建子词典,在这种情况下,此代码将起作用。正如您可能看到的那样,编译器以程序冗长为代价让您可以自由地做您想做的事。
编辑:我写的有点长 blog post about initializers 提供了更深入的解释
当你这样写代码时:
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";
它不会创建您未明确指定的任何实例。
这是 可以 工作的代码(这就是它被允许的原因)对于一些类似字典的 class,returns 空集合的键不存在,但确实会导致 KeyNotFoundException
for Dictionary
.
另一方面,这段代码:
var map = new Dictionary<string, Dictionary<string, object>>()
{
["WNodeScramblingResetZone_Unlock"] = new Dictionary<string, object>()
{
["updater"] ="pinco"
}
};
编译为:
var map = new Dictionary<string, Dictionary<string, object>>();
var tmp = new Dictionary<string, object>();
tmp["updater"] = "pinco";
map["WNodeScramblingResetZone_Unlock"] = tmp;
如您所见,这会调用 map["WNodeScramblingResetZone_Unlock"]
setter 一个新实例(而不是之前版本中的 getter ),这就是它起作用的原因。
我认为这是我第一次使用新的 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
}
};
这个语法看起来不错:没有编译错误。但是,当程序启动时,我在输出 window 中看到几个 "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
}
};
这是限制、错误,还是有具体的理由来定义它?
我使用 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
所以你必须提供 concrete 类型。您还可以使用一些动态集合,在第一次访问时自动创建子词典,在这种情况下,此代码将起作用。正如您可能看到的那样,编译器以程序冗长为代价让您可以自由地做您想做的事。
编辑:我写的有点长 blog post about initializers 提供了更深入的解释
当你这样写代码时:
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";
它不会创建您未明确指定的任何实例。
这是 可以 工作的代码(这就是它被允许的原因)对于一些类似字典的 class,returns 空集合的键不存在,但确实会导致 KeyNotFoundException
for Dictionary
.
另一方面,这段代码:
var map = new Dictionary<string, Dictionary<string, object>>()
{
["WNodeScramblingResetZone_Unlock"] = new Dictionary<string, object>()
{
["updater"] ="pinco"
}
};
编译为:
var map = new Dictionary<string, Dictionary<string, object>>();
var tmp = new Dictionary<string, object>();
tmp["updater"] = "pinco";
map["WNodeScramblingResetZone_Unlock"] = tmp;
如您所见,这会调用 map["WNodeScramblingResetZone_Unlock"]
setter 一个新实例(而不是之前版本中的 getter ),这就是它起作用的原因。