为什么我们可以使用集合初始值设定项分配只读 IList 集合? [英] Why can we assign readonly IList collection with collection initializer?

查看:18
本文介绍了为什么我们可以使用集合初始值设定项分配只读 IList 集合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

readonly ChildrenStackLayout 属性是 IList 类型.我很惊讶地知道可以为 Children 分配集合初始值设定项,如下面的代码片段所示(灵感来自 Xamarin.Forms 文档):

The readonly Children property of StackLayout is of type IList<View>. I got surprised knowing Children can be assigned with collection initializer as shown in the following code snippet (inspired by an example given by Xamarin.Forms documentation):

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

问题

当它是只读属性时为什么可以赋值?

Question

Why can it be assigned while it is a readonly property?

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

Next, I made a counter example as follows. Here the compiler complains that Children is a readonly property. It is understandable but the previous one is not. Could you tell me why?

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

    StackLayout sl = new StackLayout
    {
        Children = labels
    };
}

推荐答案

集合初始化器只是通过调用它的 Add 方法来填充集合.它不会创建它.于是下面

A collection-initializer just fills the collection by calling its Add-method. It does not create it. Thus the following

Children = { ... }

只是用于此的语法糖:

Children.Add(...);
Children.Add(...);    
Children.Add(...);
...

你看到这里假设已经一个你可以调用Add的集合,否则你会得到一个NullReferenceException.所以StackLayou 的代码大概是这样的:

You see this assumes there already is a collection on which you can call Add, otherwise you´d get a NullReferenceException. So the code of the StackLayou is probably similar to this:

class StackLayout 
{
    public readonly WhataverCollectionType Children = new WhateverCollectionType();
}

由于 WhateverCollectionType 实现了 IEnumerable 并且有一个 Add 方法,您可以使用集合初始化程序.

As WhateverCollectionType implements IEnumerable and has an Add-method, you may use a collection-initializer.

顺便说一句:实际上它有点不同,StackLayout 派生自 Layout,它将字段初始化为一些 ElementCollection,它实现了IEnumerable.

Just an asside: Actually it´s bit different, the StackLayout derives from Layout which initializes the field to some ElementCollection, which implements IEnumerable.

您的第二个示例清楚地将列表重新分配给 Children,这在 readonly 字段中是不允许的.你也可以这样写,这样更容易理解:

Your second example clearly reassigns a list to Children, which is not allowed ony a readonly-field. You could also write this, which makes this a bit easier to understand:

StackLayout sl = new StackLayout
{
    Children = new List<Label> { ... }
};

这被编译成类似这样的东西:

This is compiled to something similar to this:

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

这篇关于为什么我们可以使用集合初始值设定项分配只读 IList 集合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆