[英]Why the nested type must be explicitly declared?
I think this is the first time I'm using the new C#6 dictionary-initialization feature, and I need a nested structure like the below one: 我认为这是我第一次使用新的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
}
};
This syntax seems fine: no compilation errors. 这种语法似乎很好:没有编译错误。 However, when the program starts I see a couple of "KeyNotFoundException" errors in the output window, and the application does not work.
但是,当程序启动时,我在输出窗口中看到一些“KeyNotFoundException”错误,并且应用程序不起作用。
By the way, if I explicitly declare the nested type instantiation, everything runs fine. 顺便说一句,如果我显式声明嵌套类型实例化,一切运行正常。
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
}
};
Is that a limitation, a bug, or rather there is a concrete reason to define it? 这是一个限制,一个错误,还是有一个具体的理由来定义它?
When you write code like this: 当你编写这样的代码时:
var map = new Dictionary<string, Dictionary<string, object>>()
{
["WNodeScramblingResetZone_Unlock"] =
{
["updater"] ="pinco"
}
};
It's compiled into the equivalent of this: 它被编译成相当于:
var map = new Dictionary<string, Dictionary<string, object>>()
map["WNodeScramblingResetZone_Unlock"]["updater"] = "pinco";
It does not create any instances that you didn't explicitly specify. 它不会创建您未明确指定的任何实例。
This is code that could work (which is why it's allowed) for some dictionary-like class, which returns empty collection for keys that don't exist, but will indeed cause KeyNotFoundException
for Dictionary
. 这是代码可以工作(这就是为什么它是允许的),对于一些类似于字典的类,它返回空的集合不存在的键,但确实会导致
KeyNotFoundException
的Dictionary
。
On the other hand, this code: 另一方面,这段代码:
var map = new Dictionary<string, Dictionary<string, object>>()
{
["WNodeScramblingResetZone_Unlock"] = new Dictionary<string, object>()
{
["updater"] ="pinco"
}
};
Is compiled as: 编译为:
var map = new Dictionary<string, Dictionary<string, object>>();
var tmp = new Dictionary<string, object>();
tmp["updater"] = "pinco";
map["WNodeScramblingResetZone_Unlock"] = tmp;
As you can see, this calls the map["WNodeScramblingResetZone_Unlock"]
setter with a new instance (instead of the getter in the previous version), which is why it works. 正如您所看到的,这将使用新实例(而不是之前版本中的getter)调用
map["WNodeScramblingResetZone_Unlock"]
setter ,这就是它工作的原因。
I used http://tryroslyn.azurewebsites.net/ to translate this C# code into VB.NET: 我用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
It cleary shows that new dictionaries are not created only accessed by key. 它清晰地表明,新的词典不是仅通过密钥访问而创建的。 The new
[key] = value
syntax compiles to dictionary[key] = value
not like old one {key, value}
which compiled to dictionary.Add(key, value)
. 新的
[key] = value
语法编译为dictionary[key] = value
而不是像编译为dictionary.Add(key, value)
旧的{key, value}
。
I think this is a feature, compiler doesn't know what type of IDictionary
you need so you must provide concrete type. 我认为这是一个功能,编译器不知道你需要什么类型的
IDictionary
,所以你必须提供具体的类型。 There is also posibility that you use some dynamic collection that automatically creates subdictionnaries on first access in that case this code would work. 您还可以使用一些动态集合,在第一次访问时自动创建子代码,此代码可以使用。 As you may see compiler leaves you great freedom to do what you want at the expense of program verbosity.
正如您所看到的,编译器让您可以自由地以牺牲程序详细程度为代价来执行您想要的操作。
EDIT: I write a bit lengthy blog post about initializers that provides a more deep explanation 编辑:我写了一篇关于初始化器的博客文章 ,提供了更深入的解释
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.