1

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

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

出于此问题的目的,假设 _PhoneNumbers 是一个 List 并且它包含至少一个 PersonPhoneNumber 类的实例。

如何公开对象集合并使对象只读?此问题的根源在于必须在 WCF 数据合同中公开私有集合,但我不希望该集合可访问。

我想使用:

  Person.Mobile = "011111111111111";

代替:

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

7 回答 7

3

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

于 2011-03-01T13:05:38.283 回答
2

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

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

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

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

于 2011-03-01T13:06:51.760 回答
1

这个怎么样:

  1. 创建一个只公开只读属性的 PersonPhoneNumber 接口(没有设置器)
  2. 而不是 PersonPhoneNumber 的集合,您创建 IPersonPhoneNumber 的只读集合,但将您的 PersonPhoneNumber 项目放入其中

当然,这不会阻止代码将您的项目转换为 PersonPhoneNumber,但它确实可以防止意外修改项目的属性

于 2012-05-22T13:40:04.090 回答
0

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

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

不太好...

于 2011-03-01T13:07:32.377 回答
0

你想要的不是收藏的问题。该集合包含对您的项目的引用,您可以通过访问该集合来获取这些项目。
您可以尝试在插入之前克隆您的对象。这不会阻止它们被更改,但原始对象将被保留。否则,您必须编写只读包装器或为您的对象选择另一种构造。

于 2011-03-01T13:07:38.337 回答
0

你可能想看看这篇文章。

C# 泛型秘诀——使只读集合成为泛型方式

我认为您想要的是将电话号码列表保留为真正的私有数据成员,然后通过人员对象上的设置器和获取器公开对各种类型电话号码的访问。如果该人只能拥有每种类型中的一种,这将很好用……否则您将不得不将其更改为一种方法。像 .AddMobile("011111")

于 2011-03-01T13:12:02.877 回答
0

由于PersonPhoneNumber是一个类,因此ReadOnlyCollection您可以访问任何PersonPhoneNumber对象的引用。由于您拥有对该PersonPhoneNumber对象的引用,因此您可以执行该PersonPhoneNumber对象允许您执行的任何操作,并且它来自 a 的事实ReadOnlyCollection并不相关。

您可以考虑制作PersonPhoneNumber一个结构。如果这样做,那么当您从集合中请求索引对象时,框架会将其装箱以避免复制整个结构(为了提高效率)。但是,如果您随后尝试对其进行修改,您将收到错误“无法修改拆箱转换的结果”:

ReadOnlyPhoneNumbers[0].Number = "01111111111111";
// Cannot modify the result of an unboxing conversion

您可以将其分配给局部变量,但这将创建一个副本:

PersonPhoneNumber ppn = ReadOnlyPhoneNumbers[0].Number;
ppn.Number = "01111111111111";

ppn是一个副本。ReadOnlyCollection 中的原始内容未修改。

(Of course, before changing PersonPhoneNumber to a struct you'll need to consider the other consequences of this change. There may be other reasons that make a struct inappropriate.)

于 2016-01-07T09:05:51.230 回答