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

Asb*_*and 7 c# properties object-initializers getter-setter collection-initializer

我有这个简单的代码:

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() { }
}
Run Code Online (Sandbox Code Playgroud)

所以当我创建一个Data类时:

Data data = new Data { List = { "1", "2", "3", "4" } };
Run Code Online (Sandbox Code Playgroud)

该列表中填充了字符串"1","2","3","4",即使它没有set.

为什么会这样?

Joe*_*oey 11

您的对象初始值设定项(带有集合初始值设定项List)

Data data = new Data { List = { "1", "2", "3", "4" } };
Run Code Online (Sandbox Code Playgroud)

变成了以下内容:

var tmp = new Data();
tmp.List.Add("1");
tmp.List.Add("2");
tmp.List.Add("3");
tmp.List.Add("4");
Data data = tmp;
Run Code Online (Sandbox Code Playgroud)

以这种方式看待它应该清楚为什么你实际上是在增加string1而不是string2:tmp.List 返回 string1.您永远不会分配给属性,只需初始化返回的集合.因此,你应该看看这里的吸气剂,而不是设定器.

但是,Tim绝对正确,因为以这种方式定义的属性没有任何意义.这违反了最不惊讶的原则,对于那个类的用户而言,那里的setter所发生的事情一点也不明显.只是不要做这样的事情.

  • @Asbrand:如果您对工作原理感兴趣,我建议您下载[ILSpy](http://ilspy.net/)并在编译器输出中查看.或者阅读C#规范.当然,两者都需要习惯,但作为学习资源,它们是非常宝贵的. (2认同)