为什么我们可以使用集合初始值设定项分配只读IList集合?

Mon*_*mer 0 c# xamarin.forms

readonly Children属性StackLayout为类型IList<View>。令我惊讶的是,知道Children可以分配给集合初始值设定项,如以下代码片段所示(受Xamarin.Forms文档给出的示例启发):

public MainPage()
{   
    StackLayout sl = new StackLayout
    {
        Children =
        {
            new Label{Text="Start",HorizontalOptions=LayoutOptions.Start}
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

为什么当它是只读属性时才能分配它?

接下来,我做了一个反例如下。在这里,编译器抱怨这Children是一个只读属性。这是可以理解的,但前一个不是。你能告诉我为什么吗?

public MainPage()
{                       
    IList<Label> labels = new List<Label>
    {
        new Label{Text="Start",HorizontalOptions=LayoutOptions.Start}
    };

    StackLayout sl = new StackLayout
    {
        Children = labels
    };
}
Run Code Online (Sandbox Code Playgroud)

Him*_*ere 5

集合初始化器只是通过调用其-方法来填充集合Add。它不会创建它。因此以下

Children = { ... }
Run Code Online (Sandbox Code Playgroud)

只是语法糖:

Children.Add(...);
Children.Add(...);    
Children.Add(...);
...
Run Code Online (Sandbox Code Playgroud)

您会看到这是假定已经一个可以调用的集合Add,否则您将得到一个NullReferenceException.So的代码StackLayou可能与此类似:

class StackLayout 
{
    public readonly WhataverCollectionType Children = new WhateverCollectionType();
}
Run Code Online (Sandbox Code Playgroud)

作为WhateverCollectionType工具IEnumerable并且具有Add-method,您可以使用collection-initializer。

顺便说一句:实际上有点不同,StackLayout从其派生Layout的字段初始化为some ElementCollection,并实现IEnumerable

您的第二个示例显然将一个列表重新分配给Children,这在a readonly域中是不允许的。您也可以编写此代码,这使它更容易理解:

StackLayout sl = new StackLayout
{
    Children = new List<Label> { ... }
};
Run Code Online (Sandbox Code Playgroud)

编译成类似于以下内容:

StackLayout sl = new StackLayout(); // will also assign Children to a new list
var list = new List<Label>();
list.Add(...);
list.Add(...);
...
sl.Children = list; // this re-assigns the member which is not allowed as it is readonly
Run Code Online (Sandbox Code Playgroud)