为什么集合初始化会忽略访问修饰符

本文关键字:访问 集合 初始化 为什么 | 更新日期: 2023-09-27 18:34:53

这个答案中生成,出现了一些似乎没有意义的代码:

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>();
    }
}

乍一看,人们会认为这段代码不会编译:毕竟ListOfStrings应该有一个私有的 setter,并且不应该以这种方式分配给它。

但是,此代码编译并运行良好,并且t.ListOfStrings分配了值。

为什么此集合初始化忽略私有资源库?

为什么集合初始化会忽略访问修饰符

在您的示例中,您实际上并没有设置该属性。

C# 足够聪明,知道您正在使用 ICollection,可以使用添加、删除、清除等公开修改。 您正在执行的操作相当于以下内容:

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

如果您实际上尝试这样做,它将不起作用:

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

编辑:

由于您可能想知道如何将集合公开为只读,因此可以通过将其公开为 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>();
    }
}

您也可以创建一个只读集合,但我发现这更令人困惑。 如果将其公开为 IEnumerable,则类的使用者可以枚举项,而无法添加或删除项。

为什么此集合初始化忽略私有资源库?

其实不然。此集合初始化语法:

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

实际上由编译器转换为如下所示的内容:

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

如您所见,ListOfStrings实际上并没有被分配一个新值......