Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么反对';s值即使有不同的引用也会更改?_C#_Oop_Reference - Fatal编程技术网

C# 为什么反对';s值即使有不同的引用也会更改?

C# 为什么反对';s值即使有不同的引用也会更改?,c#,oop,reference,C#,Oop,Reference,我对这里的对象引用感到困惑。合并2个已排序的链表是一个LC问题 我知道在第一次迭代时,current.next和result引用了相同的对象,因此当我将新值分配给current.next时,result值也会改变 在第二次迭代中,r1和r2都为假,因此结果、当前和当前。下一次指向不同的对象 我不明白的是,为什么将新值赋给current(current=current.next)不会修改结果对象,而current.next=l1/l2会修改 谁能给我解释一下吗 public static List

我对这里的对象引用感到困惑。合并2个已排序的链表是一个LC问题

我知道在第一次迭代时,
current.next
result
引用了相同的对象,因此当我将新值分配给
current.next
时,
result
值也会改变

在第二次迭代中,r1和r2都为假,因此
结果、当前和当前。下一次
指向不同的对象

我不明白的是,为什么将新值赋给current(
current=current.next
)不会修改结果对象,而
current.next=l1/l2
会修改

谁能给我解释一下吗

public static ListNode MergeTwoLists(ListNode l1, ListNode l2)
        {
            if (l1 == null) return l2;
            if (l2 == null) return l1;
            if (l2 == null && l1 == null) return null;

            ListNode result = new ListNode(0);
            ListNode current = result;

            while (l1 != null && l2 != null)
            {
                var r1 = Object.ReferenceEquals(result, current);
                var r2 = Object.ReferenceEquals(result, current.next);
                
                if (l1.val < l2.val)
                {
                    current.next = l1;
                    l1 = l1.next;
                }
                else
                {
                    current.next = l2;
                    l2 = l2.next;
                }

                current = current.next;
            }

            // l1 is lognger than l2 
            if(l1 != null)
            {
                current.next = l1;
                l1 = l1.next;
            }

            // l2 is lognger than l1 
            if (l2 != null)
            {
                current.next = l2;
                l2 = l2.next;
            }

            return result.next;
        }
编辑

假设我们有这些:

Input: l1 = [1,2,4], l2 = [1,3,4]    Output: [1,1,2,3,4,4] 
第一次迭代:

r1=true
,结果和当前都指向同一对象

r2=false

l1.val==l2.val
所以我们执行

else
{
  current.next = l2;
  l2 = l2.next;
}
if (l1.val < l2.val)
{
    current.next = l1;
    l1 = l1.next;
}
目前,我们有:
result=[0,1,3,4]
current=[0,1,3,4],l2=[3,4]

接下来我们执行
current=current.Next
,因此
current=[1,3,4]
,它不再指向结果

第二次迭代

r1=false
,结果和当前都指向不同的对象

r2=false

l1.val
所以我们执行

else
{
  current.next = l2;
  l2 = l2.next;
}
if (l1.val < l2.val)
{
    current.next = l1;
    l1 = l1.next;
}
这是我不理解的部分:结果和当前指向不同的对象,仍然是当前更改时的结果。结果如何保持对当前的引用


下一步我们执行
current=current.Next
,因此
current=[1,2,4]
,所以我们修改current,但这次结果不变。

您不应该将
current.Next
分配给
l1
l2
中的节点。相反,您必须创建一个新的
ListNode
,该节点的值与
l1
l2
相同,并将
设置为当前值。下一步
指向新的
ListNode
。否则你会试图弄直一碗意大利面,这是一项不可能的任务。你需要自己做一条新的意大利面

结果和当前指向不同的对象,但当当前更改时,结果也会更改。结果如何保持对当前的引用

看看你问题的这一部分:

所以
current=[1,3,4]
它不再指向结果

重要的是,该列表中的
1
result=[0,1,3,4]
中的
1
是相同的元素。如果修改该
1
节点的
next
字段,则将修改该节点所属的任何列表。包括
结果
正在引用的列表

稍后当你写:

目前,我们有:

result = [0,1,1,2,4], current = [1,1,2,4], l2 = [3,4], l1 = [2,4]
result=[0,1,1,2,4],current=[1,1,2,4],l2=[3,4],l1=[2,4]

请注意,列表
结果
指向的对象与列表
当前
指向的对象不同。但在第一个节点之后,它是相同的

在第一次迭代之后,
result.next
引用与
current
相同的对象。这是因为
result
current
从引用同一对象开始,然后作为第一次迭代的最后一步,
current
更改为reference
current.next
。由于
current
result
在该点相同,
current.next
result.next也相同。因此,将
current
更改为
current.next
后,这与将其设置为
result.next
相同

因此,在第二次迭代中,
结果。下一次
和当前
是相同的。这意味着当您修改
current.next
时,这与修改
result.next.next
相同,其效果是将
result
列表中前两个元素之外的内容替换为引用的
l2
新元素链


再次强调:这里的关键是每个变量只指向一个节点。可以将其概念化为指向一个节点列表,但前提是您记住,如果您修改该列表中任何节点的
next
字段,您就是在修改整个列表,即使变量未引用引用列表根的变量。

也不会使用
current=current.next
指定新值。将新引用指定给变量
current
。所以它不再指向
result
引用的对象了。@YegorAndrosov是的,谢谢我得到了它们指向不同对象的部分,但在它们不断变化时仍保留一些引用。我提供了一些解释。@kenarf,result包含对0节点的引用(来自构造函数),然后在第一个操作中,您将l1或l2分配给result.next对象,最后将current分配给current.next,因此result.next变为current。当循环重复时,每个节点都被附加到结果的末尾。问题不是说代码不工作,只是他们不理解它。将两个链表变为一个合并链表并非不可能。您可能认为创建一个包含所有新节点的新链表更可取(坦白说,在没有任何上下文的情况下很难证明这一点),但这并不意味着不可能像您所说的那样对现有链表进行修改。@Servy,好吧,我从未考虑过这种方法。这肯定会更节省空间。