简体   繁体   English

为什么我允许使用对象初始化程序修改只读的属性?

[英]Why am I allowed to modify properties which are readonly with object initializers?

I have this simple code: 我有这个简单的代码:

public static void Main(String[] args)
{
    Data data = new Data { List = { "1", "2", "3", "4" } };
    foreach (var str in data.List)
        Console.WriteLine(str);
    Console.ReadLine();
}

public class Data
{
    private List<String> _List = new List<String>();
    public List<String> List
    {
        get { return _List; }
    }
    public Data() { }
}

So when I'm creating a Data class: 所以当我创建一个Data类时:

Data data = new Data { List = { "1", "2", "3", "4" } };

The list was filled with strings "1", "2", "3", "4" even if it had no set . 该列表填充了字符串“1”,“2”,“3”,“4”,即使它没有set

Why is this happening? 为什么会这样?

Your object initializer (with collection initializer for List ) 您的对象初始值设定项(带有List集合初始值设定项)

Data data = new Data { List = { "1", "2", "3", "4" } };

gets turned into the following: 变成了以下内容:

var tmp = new Data();
tmp.List.Add("1");
tmp.List.Add("2");
tmp.List.Add("3");
tmp.List.Add("4");
Data data = tmp;

Looking at it this way it should be clear why you are, in fact, adding to string1 and not to string2 : tmp.List returns string1 . 以这种方式看待它应该很清楚为什么你实际上是添加到string1而不是string2tmp.List 返回 string1 You never assign to the property, you just initialize the collection that is returned. 您永远不会分配给属性,只需初始化返回的集合。 Thus you should look at the getter here, not the setter. 因此,你应该看看这里的吸气剂,而不是设定器。

However, Tim is absolutely correct in that a property defined in that way doesn't make any sense. 但是,Tim绝对正确,因为以这种方式定义的属性没有任何意义。 This violates the principle of least surprise and to users of that class it's not at all apparent what happens with the setter there. 这违反了最不惊讶的原则,对于那个类的用户而言,那里的setter所发生的事情一点也不明显。 Just don't do such things. 只是不要做这样的事情。

That is how collection initializers work internally: 这就是集合初始化器在内部的工作方式:

Data data = new Data { List = { "1", "2", "3", "4" } };

It is basically equal to 它基本上等于

Data _d = new Data();
_d.List.Add("1");
_d.List.Add("2");
_d.List.Add("3");
_d.List.Add("4");
Data data = _d;

And _d.List uses string1 in getter. 并且_d.List在getter中使用string1

[*] More details in C# specification $ 7.6.10.3 Collection initializers [*] C#规范中的更多细节$ 7.6.10.3 Collection initializers


Change your code to this: 将您的代码更改为:

Data data = new Data { List = new List<string>{ "1", "2", "3", "4" } };

And string1 will be empty and string2 will have four items. string1将为空, string2将有四个项目。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM