C# 字典初始值设定项编译不一致

发布于 2024-08-05 12:36:00 字数 518 浏览 9 评论 0原文

以下代码可以编译,但会失败并出现 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> 

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

The following code compiles, but fails with a 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" }
        }
    };
}

If you replace the line marked 'fails' with the following, it works (as expected):

Dictionary = new Dictionary<string, string> 

Is there any purpose to the failing syntax--can it be used successfully in some other case? Or is this an oversight in the compiler?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情场扛把子 2024-08-12 12:36:00

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

这个想法

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;

一个很好的例子说明它的用处是 UI 的 Controls 集合。您可以这样做:

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

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

No, it's not a mistake... it's a flaw in your understanding of initialization syntax :)

The idea of the

Dictionary = { ... }

is for cases where the caller has read access to a collection property, but not write access. In other words, situations like this:

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

Basically it ends up being calls to Add, but without creating a new collection first. So this code:

Test test = new Test { Dictionary = { { "a", "b"}, {"c", "d" } };

is equivalent to:

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

A good example of where this is useful is with the Controls collection for a UI. You can do this:

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

but you couldn't actually set the Controls property, because it's read-only.

笑着哭最痛 2024-08-12 12:36:00

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

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

You can still use the syntax you want in a constructor:

Dictionary<string, string> dictionary = new Dictionary<string, string>
            {
                {"a", "b"},
                {"c", "d"}
            };
无所谓啦 2024-08-12 12:36:00

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

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

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

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

It fails with a null reference exception because you have declared a variable (Dictionary) that is unintialised, hence it is null.

When you attempt to add the entries into it using the initialiser syntax, you are trying to write data into a null object.

When you replace the line with a "= new Dictionary...", you are creating a new object for Dictionary to reference, and hence you are then able to add entries into it successfully.

(In Jon Skeet's example, the Controls collection must already have been created by the Form, hence it works ok)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文