.net 只读集合不是';我不是只读的。如何创建真正的ReadOnlyCollection?

.net 只读集合不是';我不是只读的。如何创建真正的ReadOnlyCollection?,.net,wcf,readonly-collection,.net,Wcf,Readonly Collection,我知道readonly集合会阻止添加/从列表中删除对象,但为什么它不阻止设置集合中对象的属性呢 System.Collections.ObjectModel.ReadOnlyCollection<PersonPhoneNumber> ReadOnlyPhoneNumbers = new System.Collections.ObjectModel.ReadOnlyCollection<PersonPhoneNumber>(_PhoneNumbers);

我知道readonly集合会阻止添加/从列表中删除对象,但为什么它不阻止设置集合中对象的属性呢

 System.Collections.ObjectModel.ReadOnlyCollection<PersonPhoneNumber> ReadOnlyPhoneNumbers = new System.Collections.ObjectModel.ReadOnlyCollection<PersonPhoneNumber>(_PhoneNumbers);
            ReadOnlyPhoneNumbers[0].Number = "01111111111111";
而不是:

Person.PhoneNumbers.Add(New PersonPhoneNumber{Number= "01111111111111", Type=Mobile});

不能将对象设置为只读。这需要改变类型。如果确实需要提供只读对象列表,则需要为要公开的每个类型创建某种类型的不可变包装器类型(或使类型从一开始就不可变)。当然,这将是一个单独的类型,如果您需要它们进行互操作,这将相当复杂…

您不能将对象设置为只读。这需要改变类型。如果确实需要提供只读对象列表,则需要为要公开的每个类型创建某种类型的不可变包装器类型(或使类型从一开始就不可变)。当然,这将是一个单独的类型,如果您需要它们进行互操作,这将是相当复杂的…

它如何防止这种情况?你将如何尝试用C#构建这样一个东西?如果支持克隆,它可能会复制从索引器(etc)返回的任何内容,但随后该对象将需要执行克隆。对于刚才给出的代码,您希望发生什么?它应该抛出异常吗?如果是这样,那就是对
PersonPhoneNumber
类本身进行更改

听起来您基本上应该将
PersonPhoneNumber
类更改为不可变。如果您需要一种以可变方式构建它的方法,您可以创建一个生成器类型,它知道如何创建
PersonPhoneNumber
-例如:

var ppn = new PersonPhoneNumber.Builder { /* set properties here }.Build();
不过,对于相当简单的类型,只需编写适当的构造函数就更容易了。

它如何防止这种情况发生?你将如何尝试用C#构建这样一个东西?如果支持克隆,它可能会复制从索引器(etc)返回的任何内容,但随后该对象将需要执行克隆。对于刚才给出的代码,您希望发生什么?它应该抛出异常吗?如果是这样,那就是对
PersonPhoneNumber
类本身进行更改

听起来您基本上应该将
PersonPhoneNumber
类更改为不可变。如果您需要一种以可变方式构建它的方法,您可以创建一个生成器类型,它知道如何创建
PersonPhoneNumber
-例如:

var ppn = new PersonPhoneNumber.Builder { /* set properties here }.Build();

不过,对于相当简单的类型,只需编写适当的构造函数就更容易了。

问题在于使对象在进入时成为只读对象-为了使这些对象成为只读对象,您需要将它们包装在某种不允许设置值的代理中

Castle的动态代理可能允许您将对象包装在自己实现的ReadOnlyProxy中。然后,add方法必须在所有内容进入集合时将其包装在ReadOnlyProxy中


不好…

问题在于使对象在进入时为只读-为了使这些对象为只读,您需要将它们包装在某种不允许设置值的代理中

Castle的动态代理可能允许您将对象包装在自己实现的ReadOnlyProxy中。然后,add方法必须在所有内容进入集合时将其包装在ReadOnlyProxy中


不好…

你想要的不是收藏的问题。集合包含对您的项目的引用,您可以通过访问集合来获取这些项目。

您可以在插入之前尝试克隆对象。这不会阻止它们被更改,但原始对象将被保留。否则,您必须为对象编写一个只读包装器或选择另一种结构。

您想要的不是集合的问题。集合包含对您的项目的引用,您可以通过访问集合来获取这些项目。

您可以在插入之前尝试克隆对象。这不会阻止它们被更改,但原始对象将被保留。否则,您必须为对象编写一个只读包装器或选择另一种结构。

您可能想看看这篇文章


我认为您想要的是保持phonenumbers列表为真正的私有数据成员,然后通过person对象上的setter和getter为各种类型的电话号码公开对它的访问。如果一个人只能拥有每种类型中的一种,这将很好地工作。。。否则,您必须将其更改为一种方法。像.AddMobile(“011111”)

您可能想看看这篇文章

我认为您想要的是保持phonenumbers列表为真正的私有数据成员,然后通过person对象上的setter和getter为各种类型的电话号码公开对它的访问。如果一个人只能拥有每种类型中的一种,这将很好地工作。。。否则,您必须将其更改为一种方法。比如.AddMobile(“011111”)

这个怎么样:

  • 为PersonPhoneNumber创建一个仅公开只读属性的接口(不带setter)
  • 您创建的不是PersonPhoneNumber的集合,而是IPersonPhoneNumber的只读集合,但将PersonPhoneNumber项放入其中
  • 当然,这并不能阻止代码将您的项目强制转换为PersonPhoneNumber,但它确实可以防止意外修改项目的属性

  • 为PersonPhoneNumber创建一个仅公开只读属性的接口(不带setter)
  • 您创建的不是PersonPhoneNumber的集合,而是IPersonPhoneNumber的只读集合,但将PersonPhoneNumber项放入其中
  • 当然,这并不能阻止代码将您的项目强制转换为PersonPhoneNumber,但它可以防止意外修改项目的属性,因为
    PersonPhoneN
    
    ReadOnlyPhoneNumbers[0].Number = "01111111111111";
    // Cannot modify the result of an unboxing conversion
    
    PersonPhoneNumber ppn = ReadOnlyPhoneNumbers[0].Number;
    ppn.Number = "01111111111111";