Return collection as read-only我在多线程环境中有一个对象,该对象维护着信息的集合,例如:
我目前用
如果基础数据存储为列表,则可以使用List(T).AsReadOnly方法。 我对您接受的答案投了赞成票,并同意它-但是我可以给您一些考虑的方法吗? 不要直接返回集合。创建一个准确命名的业务逻辑类,以反映集合的目的。 这样做的主要优点在于您无法向集合中添加代码,因此只要您在对象模型中具有本机"集合",您就始终在整个项目中散布非OO支持代码来访问它。 例如,如果您的托收是发票,则您的代码中可能有3或4个地方可以遍历未付款的发票。您可以使用getUnpaidInvoices方法。但是,当您开始考虑诸如" payUnpaidInvoices(payer,account);"之类的方法时,真正的力量就会发挥作用。 当您传递集合而不是编写对象模型时,您将永远不会经历整个重构类。 另请注意,这会使您的问题特别好。如果您不希望人们更改收藏夹,则您的容器不需要包含任何变种器。如果以后再决定仅在一种情况下实际上必须进行修改,则可以创建一种安全的机制来进行修改。 当您传递本机集合时,如何解决该问题? 而且,本机集合无法使用额外的数据进行增强。下次您发现将(Collection,Extra)传递给多个方法时,您会认识到这一点。它表示"额外"属于包含您的集合的对象。 如果您的唯一目的是使调用代码不会出错,并且在仅应读取其内容时修改集合,则只需返回不支持Add,Remove等的接口即可。为什么不返回< x0>?调用代码将不得不进行强制转换,而在不知道所访问属性的内部的情况下,他们不太可能这样做。 但是,如果您的目的是阻止调用代码观察其他线程的更新,则您必须退回到已经提到的解决方案,根据您的需要执行深层或浅层副本。 我认为您在这里混淆了概念。
绝对没有线程安全保证。
您的实现取决于您的需求: 您要使用yield关键字。您遍历IEnumerable列表,并使用yeild返回结果。这样,消费者就可以在不修改集合的情况下使用。 它看起来像这样:
应该注意的是,aku的答案只会保护列表为只读。列表中的元素仍然非常可写。我不知道是否有任何方法可以在将非原子元素放入只读列表之前对其进行克隆而无需对其进行克隆。 您可以使用集合的副本。
这样一来,是否更新就无关紧要。 |