【问题标题】:How is the interaction between LinkedList<T> and LinkedListNode<T> implemented in C#?C# 中如何实现 LinkedList<T> 和 LinkedListNode<T> 之间的交互?
【发布时间】:2013-06-12 21:09:00
【问题描述】:

首先,让我们定义一个节点:

LinkedListNode<int> node = new LinkedListNode<int>(43);

您会注意到属性node.Listnode.Nextnode.Previous 都只是get。现在让我们将节点添加到LinkedList

LinkedList<int> linkedlist = new LinkedList<int>();
linkedlist.AddFirst(node);

此时,属性node.List 将更改为包含对linkedlist 的引用。同样,如果将其他节点添加到 LinkedListNextPrevious 属性将更新以反映链表的结构,即使这些属性不公开公共 set 访问器。

这种行为是如何实现的?

我知道如何使用internal,但有更好的方法吗?例如,假设我有一个包含许多类型的程序集,而不仅仅是LinkedListLinkedListNode。通过为节点属性 ListPreviousNext 创建设置器,我将这些设置器暴露给整个程序集,这是不希望的。

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    这种行为是如何实现的?

    如果不查看源代码,我猜这些属性的设置器或支持字段标记为internal,因此可以从LinkedList&lt;T&gt; 访问,因为它们都位于同一个程序集中。

    但是有更好的方法吗?

    不是真的。让我详细说明。还有其他选择。

    1. 您可以使LinkedListNode&lt;T&gt; 成为LinkedList&lt;T&gt; 中定义的内部类。这是一种选择,但对调用者来说是个负担。

    2. 您可以将LinkedList&lt;T&gt;LinkedListNode&lt;T&gt; 雕刻到它们自己的程序集中。这显然是用户的负担,并可能很快退化为维护失败。

    我认为这两个都不是更好的解决方案。

    【讨论】:

    • 一些实现使节点类成为链表的内部类;这是解决问题的另一种方法。
    • 嗯,这增加了其他问题。我不会将其描述为一种更好的方式。
    • 嗯,通常链表中的节点是用户根本不需要知道的实现细节,这通常是这样的实现的设计方式。个人觉得这样比较好。该节点没有任何理由公开。
    • @Servy:哦,你的意思是作为一个 private 内部类。是的,我完全同意,LinkedListNote&lt;T&gt;public 总是让我感到困惑。我的回答是在 LinkedListNode&lt;T&gt; 公开的情况下,因为问题是关于如何修改 LinkedListNode&lt;T&gt; 的属性的机制,因为它们不是 public
    • @becko 你通过迭代器来实现。如果它是一个前向链表,IEnumerable 就可以了。如果您的迭代器需要额外的功能,那么您将创建具有适当功能的适当接口,并让列表本身具有创建迭代器的方法/属性。
    【解决方案2】:

    我检查了 ILSpy,只读属性由 internal 字段支持。

    internal LinkedListNode<T> next;
    
    public LinkedListNode<T> Next {
        get {
            if (this.next != null && this.next != this.list.head) {
                return this.next;
            }
            return null;
        }
    }
    

    至于如何以不同的方式进行操作,以及您是否愿意的讨论,请参阅this question 及其答案。

    【讨论】:

      【解决方案3】:

      杰森是正确的。我查看了源代码,LinkedListNode&lt;T&gt; 有内部支持字段。

      一种方法是使用嵌套类。我不知道这是否符合“更好”的方式,但它确实避免了内部设置器/字段。我省略了一些实现,所以你可以看到结构的轮廓:

      public class Node<T>
      {
        private List list;
        private Node<T> prev, next;
      
        public List List { get { return list; } }
        // other accessors.
      
        public abstract class List
        {
          Node<T> head;
      
          internal List() { }
      
          public AddFirst(Node<T> node)
          {
              // node adding logic.
              node.list = this;       
          }
      
          // implementation elided for brevity
        }
      
      }
      
      public class MyLinkedList<T> : Node<T>.List { }
      

      现在您可以声明MyLinkedList 并向其添加节点,但Node&lt;T&gt; 上没有内部访问器。

      【讨论】:

      • 所以你把LinkedList放在Node里面...我不得不说这很奇怪。
      • @becko 是的,我同意。它更多的是一种好奇心,而不是我实际上建议你实施的东西。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-15
      • 1970-01-01
      • 2010-11-08
      • 2011-04-04
      • 1970-01-01
      相关资源
      最近更新 更多