【问题标题】:Prevent List changes in C#防止 C# 中的列表更改
【发布时间】:2012-09-06 16:57:08
【问题描述】:

我在程序集 A (DLL) 中有一个对象链接列表(可以更改为任何其他 Collection 类型,只要它保持条目顺序)。

当Assembly B 从包含所述LinkedList 的类中创建一个对象时,它会分配一个方法来报告一些信息。该方法采用的参数之一是 LinkedList。

现在我希望程序集 B 中的此方法能够从该 LinkedList 中读取(遍历它并根据其内容执行操作),但是我需要防止该方法更改列表中的数据。

虽然我现在是使用程序集 A 的人,但当它公开时,我需要防止数据从我的程序集外部更改,这样使用该库的第 3 方就不会对程序集内的结果感到烦躁。

基本上,我希望“密封”将 LinkedList 从程序集 A 带到程序集 B 的参数

我说的有道理吗?

【问题讨论】:

  • 这里有两个方面,改变列表和改变列表中的元素。后者需要具有 internal 可访问性的属性设置器。
  • @HansPassant:很好。当然我的意思是改变内容

标签: c# .net linked-list readonly


【解决方案1】:
new List<T>(linkedList).AsReadOnly();

【讨论】:

  • 这可能是最好的答案——我希望不需要把它放到一个列表中——所以它不需要把它全部放在连续的内存中,但我可以忍受
【解决方案2】:

如果您可以从LinkedList&lt;T&gt; 更改为List&lt;T&gt;,您可以使用AsReadOnly() 方法生成列表的只读包装器。包装器是轻量级的,不需要复制,并且会立即将更改反映到底层集合:

List<MyClass> originalList = ...
IList<MyClass> readOnly = originalList.AsReadOnly();

【讨论】:

  • abatishchev 先说 - 抱歉 - 虽然 +1 的解释很好
  • 很好,关于 IList 的额外信息有助于使我的界面同时支持获取“临时”列表(将保留对它的引用)和您想要传递的持久列表AsReadOnly 从调用方(虽然这不是强制的,所以调用方必须小心)。
【解决方案3】:

不要将real链表传递给B的回调方法,而是传递一个副本。这样,B 就可以对列表做任何事情,而无需修改原始列表。

使用LinkedList(IEnumerable) constructor 可以轻松创建链接列表的副本:

var copy = new LinkedList<MyType>(originalList);

显然,列表的 元素 可以被 B 修改,如果它们是可变的,但我相信你知道这一点。

【讨论】:

  • 这是我想到的一件事——但是,如果 LinkedList 可能包含从对象派生的任何东西,这只会做一个浅拷贝。可能不允许添加/删除(需要确定测试),但允许更改对象内部的值 - 还是我错了?
  • 我将创建一个具有相同对象但新的LinkedListNodes 的副本。因此,它允许添加和删除,但这并不重要,因为这只会影响 B 的 LinkedList 副本。当然,修改对象本身影响 A,但这对于此处提出的所有其他解决方案都是相同的。
  • 不是真的 - 接受的答案使其只读 - 尝试更改它会在运行时引发异常
  • @537mfb:尝试更改列表(即添加或删除)将引发异常。仍然可以修改对象本身。
【解决方案4】:

我认为返回 IEnumerable&lt;T&gt; 而不是 List&lt;T&gt; 应该可以解决您的问题。最简单的方法:

foreach( var t in list )
    yield t;

这样您将只返回枚举数。消费者将无法更改列表的内容。

【讨论】:

  • 请注意,每次消费者访问此代码时,它都会迭代列表。
  • @abatishchev 没有什么能阻止开发人员做一次、缓存它,并且只有在添加、删除元素时才进行迭代......提供这个 sn-p 只是为了说明这个想法。跨度>
  • 列表的内容应该在每次报告回电之前更改一次,所以这对于我的特殊情况来说太麻烦了 - 不过很好
【解决方案5】:

你能发布一些代码吗?

听起来您想让他们使用数据的副本。这样,如果他们确实以某种方式对其进行了更改,原始副本将保持不变。

查看用于复制对象的 ICloneable 接口并创建一个全新的链表,其中包含所有原始内容的副本并将其传递回程序集 B。

【讨论】:

  • 这绝对是一个可能的解决方案——尽管它必须是一个深拷贝——问题是由于无法确定 LinkedList 中的对象是 IClonable 并且甚至不知道它们是什么类型是,它们甚至可能来自第 3 方自定义类
猜你喜欢
  • 2011-01-10
  • 1970-01-01
  • 1970-01-01
  • 2020-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-20
  • 1970-01-01
相关资源
最近更新 更多