C# LinkedList节点无法关联:如何正确实现节点链接?
嘿,我一眼就看出问题所在了——你在使用.NET自带的LinkedList<T>时,踩了一个很容易犯的坑:手动实例化LinkedListNode<T>并直接添加到链表中。
核心原因
.NET的LinkedList<T>内部会自行管理节点的创建和链接关系。当你调用AddLast(T value)这类方法时,链表会自动创建对应的LinkedListNode<T>实例,并维护它的Next和Previous引用,把它纳入双向链表的结构里。但如果你自己new一个LinkedListNode<T>再添加进去,这个节点根本不属于链表的内部管理体系,它的Next和Previous自然永远是null,这就是为什么你的统计结果始终为0。
修正方案
我们完全不需要自定义双向链表,只要正确使用.NET自带的LinkedList<T>就可以解决问题,调整如下:
1. 修改DependencyTree类的定义与构造函数
首先,把泛型继承从LinkedList<LinkedListNode<TTreeLeaf>>改成LinkedList<TTreeLeaf>——因为LinkedList<T>本身就是用来管理T类型元素的双向链表,节点是封装在内部的,你不需要直接操作LinkedListNode:
public abstract class DependencyTree<TTreeLeaf, TTreeLeafNode> : LinkedList<TTreeLeaf> where TTreeLeaf : DependencyTreeLeaf where TTreeLeafNode : DependencyTreeLeafNode { #region Constructors public DependencyTree(ICollection<TTreeLeaf> leaves) { foreach (var leaf in leaves) { AddLast(leaf); // 让链表自动创建节点并维护链接 } // 现在正确统计有链接的节点数量 var nodeCount = this.Select(leaf => Find(leaf)) .Count(node => node.Next != null || node.Previous != null); Console.WriteLine(nodeCount.ToString()); } #endregion Constructors }
这里注意:LinkedList<T>遍历出来的是元素本身,不是节点,所以需要用Find方法获取对应的节点实例,再判断Next和Previous。
2. 修正DependencyTreeLeaf类的问题
你补充的代码里也存在同样的错误,把DependencyTreeLeaf的继承改成LinkedList<DependencyTreeLeafNode>,并直接添加元素即可:
public abstract class DependencyTreeLeaf : LinkedList<DependencyTreeLeafNode> { public LinkedList<DependencyTreeLeaf> Children { get; private set; } public DependencyState SiblingForwardDependency { get; } public DependencyState ChildDownwardDependency { get; } public DependencyTreeLeaf(IEnumerable<DependencyTreeLeafNode> leafNodes, DependencyState siblingDependency = DependencyState.Unset, IEnumerable<DependencyTreeLeaf> children = null, DependencyState childDependency = DependencyState.Unset) { foreach (var leafNode in leafNodes) { AddLast(leafNode); // 链表自动处理节点创建与链接 } if (children != null) { Children = new LinkedList<DependencyTreeLeaf>(); foreach (var childLeaf in children) { Children.AddLast(childLeaf); // 同样直接添加元素,无需手动创建节点 } } SiblingForwardDependency = siblingDependency; ChildDownwardDependency = childDependency; } }
额外说明
只有当你需要在特定节点的前后插入/删除元素时,才需要主动获取LinkedListNode<T>(比如通过Find或AddLast的返回值)。日常添加元素时,直接操作元素本身就好,LinkedList<T>会帮你搞定所有节点链接的细节。
内容的提问来源于stack exchange,提问作者Rice

