You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#自定义队列引用赋值疑问:为何_last更新不影响_first?

C#自定义队列Add方法中引用赋值逻辑解析

我在调试一段C#自定义队列代码时,对变量的赋值逻辑感到困惑:

  • 第一次调用Add()时,_first为null,会被赋值为_last,此时二者指向同一个节点。
  • 第二次调用Add()时,_last不为null,新节点会被赋值给_last.Next,由于_first和_last指向同一个节点,_first.Next也会同步更新。
  • 但执行_last = t;时,只有_last指向了新节点,_first却依然指向原来的节点,这是为什么?

自定义队列代码

public class QueueCustom<T>
{
    public class QueueNode<T>
    {
        public T Data;
        public QueueNode<T>? Next;

        public QueueNode(T data)
        {
            this.Data = data;
        }
    }

    private QueueNode<T>? _first;
    private QueueNode<T>? _last;

    public void Add(T item)
    {
        var t = new QueueNode<T>(item);

        if (_last != null)
        {
            _last.Next = t; // 此时_first和_last指向同一个节点,_first.Next也会被更新
        }

        _last = t; // 为什么只有_last指向新节点,_first不会跟着变?

        _first ??= _last;
    }

    public T Remove()
    {
        if (_first == null)
        {
            throw new InvalidOperationException("Queue is empty");
        }

        T data = _first.Data;
        _first = _first.Next;

        if (_first == null)
        {
            _last = null;
        }

        return data;
    }
}

调用代码

var queue = new QueueCustom<int>();
queue.Add(1);
queue.Add(2);
queue.Add(3);

核心原因:引用变量和对象的区别

在C#中,_first和_last都是引用类型变量,它们本身存储的是堆上对象的内存地址,而非对象本身。

  1. 第一次Add后的状态:
    创建第一个节点QueueNode(1),_last被赋值为这个节点,然后_first ??= _last让_first也指向同一个节点。此时_first和_last的内存地址值完全相同,都指向堆上的同一个节点对象。

  2. 第二次Add时的_last.Next = t:
    这行代码是修改堆上节点对象的属性——通过_last找到它指向的节点,把该节点的Next属性设置为新创建的t(QueueNode(2))。因为_first指向的是同一个节点对象,所以_first.Next自然也会看到这个变化,本质是同一个对象的属性被修改了。

  3. 执行_last = t的本质:
    这行代码是修改_last这个引用变量本身的值——把_last存储的内存地址替换成新节点t的地址。而_first这个引用变量存储的还是原来第一个节点的地址,所以它不会指向新节点。

简单类比:把_first和_last看成两张纸条,上面写着箱子的位置。第一次Add后,两张纸条都写着第一个箱子的位置。修改箱子里的东西(_last.Next = t),不管看哪张纸条找过去,箱子里的内容都变了。但如果把其中一张纸条上的地址改成第二个箱子的位置(_last = t),另一张纸条上的地址还是第一个箱子的,自然不会指向新箱子。


内容的提问来源于stack exchange,提问作者Josh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 10:34:59