Why does collection initialization ignore access modifiers? [duplicate]

人盡茶涼 提交于 2019-12-11 12:18:59

问题


Spawing from this answer, some code appeared that seems to not make sense:

class Program
{
    static void Main(string[] args)
    {
        var t = new Testing
        {
            ListOfStrings =
            { 
                "hello", 
                "goodbye" 
            }
        };

        Console.ReadKey();
    }
}

public class Testing
{
    public List<string> ListOfStrings { get; private set; }

    public Testing()
    {
        ListOfStrings = new List<string>();
    }
}

At first glance one would think this code wouldn't compile: after all ListOfStrings is supposed to have a private setter, and shouldn't be able to be assigned to in this manner.

However, this code compiles and runs fine, and t.ListOfStrings has the values assigned.

Why does this collection initialization ignore the private setter?


回答1:


In your example you are not actually setting the property.

C# is smart enough to know that you are using an ICollection which can be publicly modified using Add, Remove, Clear, etc. What you are doing is the equivalent of this:

t.AddRange(new string[] { "hello", "goodbye" });

If you actually tried to do this it would not work:

var t = new Testing
{
    ListOfStrings = new List<string>(),
};

EDIT:

Since you might be wondering how to expose a collection as readonly, you can do this by just exposing it as an IEnumerable:

public class Testing
{
    private List<string> _listOfStrings;
    public IEnumerable<string> MyStrings
    {
        get
        {
            foreach (var s in _myStrings)
                yield return s;
        }
    }

    public Testing()
    {
        _listOfStrings = new List<string>();
    }
}

You could also create a readonly collection but I find that is more confusing. If you expose it as IEnumerable then consumers of the class can enumerate through the items with no ability to add or remove items.




回答2:


Why does this collection initialization ignore the private setter?

It doesn't. This collection initialization syntax :

    var t = new Testing
    {
        ListOfStrings =
        { 
            "hello", 
            "goodbye" 
        }
    };

is actually transformed by the compiler to something like this:

var t = new Testing();
t.ListOfStrings.Add("hello");
t.ListOfStrings.Add("goodbye");

So as you can see, ListOfStrings isn't actually assigned a new value...



来源:https://stackoverflow.com/questions/19305074/why-does-collection-initialization-ignore-access-modifiers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!