[英]Why can we assign readonly IList collection with collection initializer?
StackLayout
的readonly
Children
屬性的類型為IList<View>
。 我驚訝地得知,可以為Children
分配集合初始值設定項,如以下代碼片段所示(受Xamarin.Forms文檔給出的示例的啟發):
public MainPage()
{
StackLayout sl = new StackLayout
{
Children =
{
new Label{Text="Start",HorizontalOptions=LayoutOptions.Start}
}
};
}
為什么當它是只讀屬性時才能分配它?
接下來,我做了一個反例如下。 在這里,編譯器抱怨Children
是一個只讀屬性。 這是可以理解的,但前一個不是。 你能告訴我為什么嗎?
public MainPage()
{
IList<Label> labels = new List<Label>
{
new Label{Text="Start",HorizontalOptions=LayoutOptions.Start}
};
StackLayout sl = new StackLayout
{
Children = labels
};
}
集合初始化器只是通過調用其Add
方法來填充集合。 它不會創建它。 因此以下
Children = { ... }
只是語法糖:
Children.Add(...);
Children.Add(...);
Children.Add(...);
...
您將看到這是假設已經存在一個可以調用Add
的集合,否則您將獲得NullReferenceException.
因此, StackLayou
的代碼可能與此類似:
class StackLayout
{
public readonly WhataverCollectionType Children = new WhateverCollectionType();
}
由於WhateverCollectionType
實現IEnumerable
並具有Add
方法,因此您可以使用collection-initializer。
StackLayout
:實際上有點不同, StackLayout
派生自Layout
,該Layout
將字段初始化為一些實現IEnumerable
ElementCollection
。
您的第二個示例清楚地將列表重新分配給Children
,僅在readonly
字段中不允許該列表。 您也可以編寫此代碼,這使它更容易理解:
StackLayout sl = new StackLayout
{
Children = new List<Label> { ... }
};
編譯成類似於以下內容:
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
因為在第一種情況下,您正在構造(創建)它,而不是分配。 在第二種情況下,您正在嘗試對其進行修改
在文檔的示例中,沒有創建List<Label>
並將其分配給Children
屬性的新實例。 以下代碼僅在現有實例上調用方法Add()
。
Children =
{
new Label{Text="Start",HorizontalOptions=LayoutOptions.Start}
}
基本上它只是調用
sl.Children.Add(new Label{Text="Start",HorizontalOptions=LayoutOptions.Start});
另一方面,這也會失敗,因為它將為Children
屬性分配一個新實例:
Children = new List<Label>
{
new Label{Text="Start",HorizontalOptions=LayoutOptions.Start}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.