以下代码编译,但失败并显示NullReferenceException
:
class Test
{
public Dictionary<string, string> Dictionary { get; set; }
}
static void Main(string[] args)
{
var x = new Test
{
Dictionary = // fails
{
{ "key", "value" }, { "key2", "value2" }
}
};
}
如果用以下内容替换标记为“失败”的行,则可以正常工作(如预期的那样):
Dictionary = new Dictionary<string, string>
语法失败是否有任何目的 - 是否可以在其他情况下成功使用?或者这是编译器的疏忽?
答案 0 :(得分:32)
不,这不是一个错误......这是你理解初始化语法的一个缺陷:)
的想法
Dictionary = { ... }
适用于调用者具有读取访问集合属性但不能写访问权限的情况。换句话说,这样的情况:
class Test
{
private readonly Dictionary<string, string> dictionary
= new Dictionary<string, string>();
public Dictionary<string, string> Dictionary { get { return dictionary; } }
}
基本上它最终会调用Add,但不会先创建新的集合。所以这段代码:
Test test = new Test { Dictionary = { { "a", "b"}, {"c", "d" } };
相当于:
Test tmp = new Test();
Dictionary<string, string> tmpDictionary = tmp.Dictionary;
tmpDictionary.Add("a", "b");
tmpDictionary.Add("c", "d");
Test test = tmp;
有用的一个很好的例子是用户界面的Controls
集合。你可以这样做:
Form form = new Form
{
Controls =
{
new Button { Text = "Hi" },
new TextBox { Text = "There" }
}
};
但您实际上无法设置 Controls
属性,因为它是只读的。
答案 1 :(得分:4)
您仍然可以在构造函数中使用所需的语法:
Dictionary<string, string> dictionary = new Dictionary<string, string>
{
{"a", "b"},
{"c", "d"}
};
答案 2 :(得分:1)
它因空引用异常而失败,因为您声明了一个未初始化的变量(Dictionary),因此它为null。
当您尝试使用初始化语法将条目添加到其中时,您尝试将数据写入空对象。
当您使用“= new Dictionary ...”替换该行时,您正在为要引用的Dictionary创建一个新对象,因此您可以成功地向其中添加条目。
(在Jon Skeet的例子中,Controls集合必须已经由Form创建,因此它可以正常工作)