【问题标题】:C# dictionary initializer compilation inconsistencyC# 字典初始化程序编译不一致
【发布时间】:2010-11-30 21:12:30
【问题描述】:

以下代码编译,但失败并显示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> 

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

【问题讨论】:

    标签: c# compiler-construction syntax dictionary initializer


    【解决方案1】:

    不,这不是错误...这是您对初始化语法的理解有缺陷:)

    想法

    Dictionary = { ... }
    

    适用于调用者对集合属性具有读取访问权限但没有写入访问权限的情况。换句话说,像这样的情况:

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

    基本上它最终被调用添加,但没有先创建一个新集合。所以这段代码:

    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;
    

    一个很好的例子就是 UI 的 Controls 集合。你可以这样做:

    Form form = new Form
    {
        Controls = 
        {
            new Button { Text = "Hi" }, 
            new TextBox { Text = "There" } 
        }
    };
    

    但您实际上无法设置 Controls 属性,因为它是只读的。

    【讨论】:

    • 所以它用于将项目添加到由构造函数创建的字典中——我应该意识到这一点。但它是等号运算符的一种奇怪用法,因为其效果是添加到字典中已有的内容(构造函数可能首先添加了项目)。
    • 有点,是的......但同时它用于设置集合中的初始值,因此它适合这种方式。
    • 对。缺少的new 应该是一个危险信号.. 但是我从来没有使用过这种语法,所以我把等于运算符太字面化了。
    【解决方案2】:

    你仍然可以在构造函数中使用你想要的语法:

    Dictionary<string, string> dictionary = new Dictionary<string, string>
                {
                    {"a", "b"},
                    {"c", "d"}
                };
    

    【讨论】:

      【解决方案3】:

      它因空引用异常而失败,因为您声明了一个未初始化的变量(字典),因此它为空。

      当您尝试使用初始化语法将条目添加到其中时,您正在尝试将数据写入空对象。

      当您用“= new Dictionary...”替换该行时,您正在创建一个供 Dictionary 引用的新对象,因此您可以成功地向其中添加条目。

      (在 Jon Skeet 的示例中,Controls 集合必须已经由 Form 创建,因此可以正常工作)

      【讨论】:

      • 很公平。乔恩回答了你的问题,所以我想我会填写原因,以防你不理解失败。
      猜你喜欢
      • 2012-01-21
      • 2011-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-05
      • 2011-02-17
      • 1970-01-01
      相关资源
      最近更新 更多