C#字典初始化程序编译不一致

Ben*_*n M 11 c# compiler-construction syntax dictionary initializer

以下代码编译,但失败并带有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" }
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

如果用以下内容替换标记为"失败"的行,则可以正常工作(如预期的那样):

Dictionary = new Dictionary<string, string> 
Run Code Online (Sandbox Code Playgroud)

失败的语法是否有任何目的 - 是否可以在其他情况下成功使用?或者这是编译器的疏忽?

Jon*_*eet 32

不,这不是一个错误......这是你理解初始化语法的一个缺陷:)

的想法

Dictionary = { ... }
Run Code Online (Sandbox Code Playgroud)

适用于调用者具有对集合属性的访问权但不具有访问权的情况.换句话说,这样的情况:

class Test
{
    private readonly Dictionary<string, string> dictionary 
        = new Dictionary<string, string>();
    public Dictionary<string, string> Dictionary { get { return dictionary; } }
}
Run Code Online (Sandbox Code Playgroud)

基本上它最终会调用Add,但不会先创建新的集合.所以这段代码:

Test test = new Test { Dictionary = { { "a", "b"}, {"c", "d" } };
Run Code Online (Sandbox Code Playgroud)

相当于:

Test tmp = new Test();
Dictionary<string, string> tmpDictionary = tmp.Dictionary;
tmpDictionary.Add("a", "b");
tmpDictionary.Add("c", "d");
Test test = tmp;
Run Code Online (Sandbox Code Playgroud)

这有用的一个很好的例子是ControlsUI 的集合.你可以这样做:

Form form = new Form
{
    Controls = 
    {
        new Button { Text = "Hi" }, 
        new TextBox { Text = "There" } 
    }
};
Run Code Online (Sandbox Code Playgroud)

但你不能真正设置Controls属性,因为它是只读的.