关于c#:以只读方式返回集合

关于c#:以只读方式返回集合

Return collection as read-only

我在多线程环境中有一个对象,该对象维护着信息的集合,例如:

1
2
3
4
5
6
7
public IList<string> Data
{
    get
    {
        return data;
    }
}

我目前用ReaderWriterLockSlim包裹了return data;,以保护集合免于共享冲突。 但是,可以肯定的是,我想将集合返回为只读状态,以便调用代码无法更改集合,而仅查看已经存在的内容。 这是可能吗?


如果基础数据存储为列表,则可以使用List(T).AsReadOnly方法。
如果您的数据可以枚举,则可以使用Enumerable.ToList方法将您的集合转换为List并对其调用AsReadOnly。


我对您接受的答案投了赞成票,并同意它-但是我可以给您一些考虑的方法吗?

不要直接返回集合。创建一个准确命名的业务逻辑类,以反映集合的目的。

这样做的主要优点在于您无法向集合中添加代码,因此只要您在对象模型中具有本机"集合",您就始终在整个项目中散布非OO支持代码来访问它。

例如,如果您的托收是发票,则您的代码中可能有3或4个地方可以遍历未付款的发票。您可以使用getUnpaidInvoices方法。但是,当您开始考虑诸如" payUnpaidInvoices(payer,account);"之类的方法时,真正的力量就会发挥作用。

当您传递集合而不是编写对象模型时,您将永远不会经历整个重构类。

另请注意,这会使您的问题特别好。如果您不希望人们更改收藏夹,则您的容器不需要包含任何变种器。如果以后再决定仅在一种情况下实际上必须进行修改,则可以创建一种安全的机制来进行修改。

当您传递本机集合时,如何解决该问题?

而且,本机集合无法使用额外的数据进行增强。下次您发现将(Collection,Extra)传递给多个方法时,您会认识到这一点。它表示"额外"属于包含您的集合的对象。


如果您的唯一目的是使调用代码不会出错,并且在仅应读取其内容时修改集合,则只需返回不支持Add,Remove等的接口即可。为什么不返回< x0>?调用代码将不得不进行强制转换,而在不知道所访问属性的内部的情况下,他们不太可能这样做。

但是,如果您的目的是阻止调用代码观察其他线程的更新,则您必须退回到已经提到的解决方案,根据您的需要执行深层或浅层副本。


我认为您在这里混淆了概念。

ReadOnlyCollection为现有集合提供只读包装,允许您(A类)在调用者(B类)无法修改集合(即无法添加或删除)的前提下传递对集合安全的引用。集合中的任何元素。)

绝对没有线程安全保证。

  • 如果您(A类)在将其作为ReadOnlyCollection分发后继续修改基础集合,则B类将看到这些更改,使任何迭代器无效等,并且通常对集合中的任何常见并发问题持开放态度。 。
  • 此外,如果集合中的元素是可变的,您(A类)和调用者(B类)都将能够更改集合中对象的任何可变状态。

您的实现取决于您的需求:
-如果您不关心呼叫者(B类)是否对集合有任何进一步的更改,则可以克隆该集合,将其分发出去并停止维护。
-如果您确实需要调用方(B类)查看对该集合所做的更改,并且希望此操作是线程安全的,那么您手头上还有更多问题。一种可能性是实现您自己的ReadOnlyCollection的线程安全变体以允许锁定访问,但是如果您要支持IEnumerable,这将是不平凡且不可靠的,并且仍然无法保护您免受IEnumerable中的可变元素的影响。采集。


您要使用yield关键字。您遍历IEnumerable列表,并使用yeild返回结果。这样,消费者就可以在不修改集合的情况下使用。

它看起来像这样:

1
2
3
4
5
6
7
8
9
10
11
List<string> _Data;
public IEnumerable<string> Data
{
  get
  {
    foreach(string item in _Data)
    {
      return yield item;
    }
  }
}

应该注意的是,aku的答案只会保护列表为只读。列表中的元素仍然非常可写。我不知道是否有任何方法可以在将非原子元素放入只读列表之前对其进行克隆而无需对其进行克隆。


您可以使用集合的副本。

1
2
3
4
public IList<string> Data {
get {
    return new List< T >(data);
}}

这样一来,是否更新就无关紧要。


推荐阅读

    常识硬件的计算机日常维护

    常识硬件的计算机日常维护,,硬件(防尘、防高温、防磁、防潮、防静电、防震) 应将电脑放在一个干净的房间,避免灰尘太多造成的不利影响,对各种

    移动硬盘如何使用移动硬盘维护知识

    移动硬盘如何使用移动硬盘维护知识,,现在移动硬盘的广泛使用和快节奏的工作使拆迁的一部分;驱动;人,我们说不;拆除;拆除手段,在硬盘有意无意的操

    如何将只读文件从CD-ROM复制到计算机

    如何将只读文件从CD-ROM复制到计算机,,我借了几张光盘,里面的东西很好。我想把CD中的只读文件复制到计算机上,但是计算机提示不能复制。把光

    多线程cpu电脑|多线程的CPU

    多线程cpu电脑|多线程的CPU,,1. 多线程的CPU四核心四线程,表示这个电脑的CPU核心是4个核心、4个线程的。电脑CPU的核心数量和线程数量越多,

    台式电脑维护维修|台式电脑维修教程

    台式电脑维护维修|台式电脑维修教程,,1. 台式电脑维修教程一,保修没过的话送修;二,已过保修的话,一般也很难找的到会修电源的电脑店,电脑配置较

    网吧计算机维护的终极技巧

    网吧计算机维护的终极技巧,,互联网是一个基本的组装电脑,电脑配置也不错,但很多软件需要安装,互联网毕竟是维护国内计算机一般他们的爱情,最需

    联想电脑维护|联想电脑维护软件

    联想电脑维护|联想电脑维护软件,,联想电脑维护软件什么情况,联想电脑硬件维修,保修期内一般应该是在48小时修复,如果过了保修期,需要返厂维修,

    苹果电脑u盘只读|苹果电脑u盘只能读

    苹果电脑u盘只读|苹果电脑u盘只能读,,苹果电脑u盘只能读 U盘不需要卸载就能够读出来的,因为我们U盘的话,他们基本上是一个移动文件的一个工

    wpsisppt设置只读|WPS设置只读文件

    wpsisppt设置只读|WPS设置只读文件,如何设置,wpsisppt,1.WPS怎样设置只读文件您好,很高兴为您解答!标题和内容不是一个问题?设置只读文件,在[W