【问题标题】:Readonly wrapper of a LinkedList. HowTo?链接列表的只读包装器。如何?
【发布时间】:2009-11-19 11:22:24
【问题描述】:

.NET v2

当List有一个非常有用的(4我)方法AsReadOnly() LinkedList 没有这样的方法。

有没有办法“快速”连接内部 LinkedList 以仅从外部代码中读取?

【问题讨论】:

    标签: .net list .net-2.0 readonly


    【解决方案1】:

    为什么不直接返回IEnumerable<T>?如果您只想让用户枚举列表而不修改它*,IEnumerable 是显而易见的选择。

    如果你想拥有一个LinkedList接口的只读接口,你可以包装LinkedList,将只读方法转发到被包装的列表并拒绝任何更改。

    *) 请记住,ReadOnlyCollection 和 IEnumerable 都不会阻止调用者在引用类型集合的情况下更改对象的状态。如果对象也应该是只读的,则需要将其作为其类型的一部分来实现。

    【讨论】:

    • 我假设您想返回 LinkedList 的只读版本。您可以通过将其作为 IEnumerable 返回来执行此操作。这将允许调用者枚举列表,但不能修改它。
    • 如果这些方法很重要,那么你必须包装 LinkedList 并基本上做 ReadOnlyCollection 所做的事情。
    • 你有理由。不幸的是,我没有创建包装器或 ReadOnlyCollection 的经验。所以一个小样本会很有帮助。谢谢。
    【解决方案2】:

    ReadOnlyCollection<T>IList<T> 作为构造函数的参数。 LinkedList<T> 没有实现这个接口。 List<T> 有一个以IEnumerable<T> 作为参数的构造函数重载,LinkedList<T> 实现了这个接口。所以以下应该工作:

    LinkedList<int> linked = new LinkedList<int>();
    // populate the list
    
    ReadOnlyCollection<int> readOnly = new ReadOnlyCollection<int>(
        new List<int>(linked));
    

    它使用List&lt;T&gt; 的实例将项目携带到ReadOnlyCollection&lt;T&gt; 构造函数中。

    【讨论】:

    • 抱怨想要一个只读的LinkedList 而不是IList(问题,而不是答案)
    • 由于未知原因,LinkedListNode 被密封,LinkedList 没有虚拟方法,因此您只能使用不可变节点编写自己的双向链表
    【解决方案3】:

    #1 修复链表

    class FixedLinkedList<T> : LinkedList<T>, IList<T>
    {
        public T this[int index]
        {
            get
            {
                return GetAt(index).Value;
            }
            set
            {
                GetAt(index).Value = value;
            }
        }
    
        public int IndexOf(T item)
        {
            int i = 0;
            var node = First;
            while (node!= null && !node.Value.Equals(item))
            {
                i++;
                node = node.Next;
            }
    
            if (node == null)
            {
                return -1;
            }
    
            return i;
        }
    
        public void Insert(int index, T item)
        {
            AddBefore(GetAt(index), new LinkedListNode<T>(item));
        }
    
    
        public void RemoveAt(int index)
        {
            Remove(GetAt(index));
        }
    
        private LinkedListNode<T> GetAt(int index)
        {
            CheckIndex(index);
            int i = 0;
            var node = First;
            while (i < index)
            {
                i++;
                node = node.Next;
            }
    
            return node;
        }
    
        private void CheckIndex(int index)
        {
            if (index < 0)
            {
                throw new ArgumentOutOfRangeException(
                    nameof(index),
                    "Parameter must be greater or equal to 0.");
            }
    
            if (index >= Count)
            {
                throw new ArgumentOutOfRangeException(
                    nameof(index),
                    "Parameter must be lower than the list item Count.");
            }
        }
    }
    

    #2 将其实例包装在 ReadOnlyCollection 中

    【讨论】:

      【解决方案4】:

      LinkedList&lt;T&gt; 没有实现IList 所以简而言之,没有没有办法快速做到这一点。如果您将 LinkedList 转换为 List,您可能会失去所需的功能。

      LinkedList&lt;T&gt; 没有为您提供任何子类化功能,因此您需要自己编写。我想下一个请求是“你能告诉我怎么做吗”

      【讨论】:

      • 返回列表好吗?或者你需要它是LinkedList
      • 我更喜欢链接只读列表
      猜你喜欢
      • 2013-10-14
      • 2011-02-08
      • 1970-01-01
      • 2012-04-03
      • 1970-01-01
      • 2014-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多