ref 传递的列表 - 帮我解释一下这种行为

发布于 2024-10-05 06:49:28 字数 1027 浏览 4 评论 0原文

看一下下面的程序:

class Test
{
    List<int> myList = new List<int>();

    public void TestMethod()
    {
        myList.Add(100);
        myList.Add(50);
        myList.Add(10);

        ChangeList(myList);

        foreach (int i in myList)
        {
            Console.WriteLine(i);
        }
    }

    private void ChangeList(List<int> myList)
    {
        myList.Sort();

        List<int> myList2 = new List<int>();
        myList2.Add(3);
        myList2.Add(4);

        myList = myList2;
    }
}

我假设 myList 会通过 ref 传递,并且输出会

3
4

The list is确实“通过 ref 传递”,但只有 >sort 函数生效。以下语句 myList = myList2; 无效。

所以输出实际上是:

10
50
100

你能帮我解释一下这个行为吗?如果 myList 确实不是passed-by-ref(因为 myList = myList2 没有生效),那么 myList 如何.Sort() 生效吗?

我什至假设该声明不会生效,并且输出为:

100
50
10

Take a look at the following program:

class Test
{
    List<int> myList = new List<int>();

    public void TestMethod()
    {
        myList.Add(100);
        myList.Add(50);
        myList.Add(10);

        ChangeList(myList);

        foreach (int i in myList)
        {
            Console.WriteLine(i);
        }
    }

    private void ChangeList(List<int> myList)
    {
        myList.Sort();

        List<int> myList2 = new List<int>();
        myList2.Add(3);
        myList2.Add(4);

        myList = myList2;
    }
}

I assumed myList would have passed by ref, and the output would

3
4

The list is indeed "passed by ref", but only the sort function takes effect. The following statement myList = myList2; has no effect.

So the output is in fact:

10
50
100

Can you help me explain this behavior? If indeed myList is not passed-by-ref (as it appears from myList = myList2 not taking effect), how does myList.Sort() take effect?

I was assuming even that statement to not take effect and the output to be:

100
50
10

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

孤星 2024-10-12 06:49:29

您正在传递对列表的引用,但您没有通过引用传递列表变量 - 因此,当您调用 ChangeList 时 变量的(即引用 - 认为“指针”)被复制 - 并更改为 ChangeList< 内的参数值 /code> TestMethod 看不到

try:

private void ChangeList(ref List<int> myList) {...}
...
ChangeList(ref myList);

然后传递对本地变量的引用myRef(如TestMethod中声明的);现在,如果您在 ChangeList 内重新分配参数,您也会在 TestMethod 内重新分配变量内部

You are passing a reference to the list, but your aren't passing the list variable by reference - so when you call ChangeList the value of the variable (i.e. the reference - think "pointer") is copied - and changes to the value of the parameter inside ChangeList aren't seen by TestMethod.

try:

private void ChangeList(ref List<int> myList) {...}
...
ChangeList(ref myList);

This then passes a reference to the local-variable myRef (as declared in TestMethod); now, if you reassign the parameter inside ChangeList you are also reassigning the variable inside TestMethod.

春风十里 2024-10-12 06:49:29

这是一种简单的理解方法

  • 您的列表是在堆上创建的对象。变量 myList 是一个
    对该对象的引用。

  • 在 C# 中,您从不传递对象,而是按值传递它们的引用。

  • < p>当您通过传入的引用访问列表对象时
    ChangeList(例如,在排序时)原始列表会发生更改。

  • ChangeList 方法的赋值是对引用的值进行的,因此不会对原始列表进行任何更改(仍在堆上,但不再在方法变量上引用)。< /p>

Here is an easy way to understand it

  • Your List is an object created on heap. The variable myList is a
    reference to that object.

  • In C# you never pass objects, you pass their references by value.

  • When you access the list object via the passed reference in
    ChangeList (while sorting, for example) the original list is changed.

  • The assignment on the ChangeList method is made to the value of the reference, hence no changes are done to the original list (still on the heap but not referenced on the method variable anymore).

违心° 2024-10-12 06:49:29

链接将帮助您理解 C# 中的引用传递。
基本上,当引用类型的对象按值传递给方法时,只有该对象上可用的方法才能修改对象的内容。

例如,List.sort() 方法更改列表内容,但如果您将某个其他对象分配给同一变量,则该分配对于该方法来说是本地的。这就是 myList 保持不变的原因。

如果我们使用 ref 关键字传递引用类型的对象,那么我们可以将一些其他对象分配给同一个变量,这会改变整个对象本身。

(编辑:this 是上面链接的文档的更新版本。)

This link will help you in understanding pass by reference in C#.
Basically,when an object of reference type is passed by value to an method, only methods which are available on that object can modify the contents of object.

For example List.sort() method changes List contents but if you assign some other object to same variable, that assignment is local to that method. That is why myList remains unchanged.

If we pass object of reference type by using ref keyword then we can assign some other object to same variable and that changes entire object itself.

(Edit: this is the updated version of the documentation linked above.)

笔芯 2024-10-12 06:49:29

C# 在按值传递时只会执行浅复制,除非相关对象执行 ICloneable(显然 List 类不会执行)。

这意味着它复制 List 本身,但对列表内对象的引用保持不变;也就是说,指针继续引用与原始 List 相同的对象。

如果您更改新 List 引用的内容的值,您也会更改原始 List (因为它引用相同的对象)。但是,您随后将 myList 引用的内容完全更改为新的 List,现在只有原始 List 引用这些整数。

阅读 这篇关于“传递参数”的 MSDN 文章了解更多信息。

“如何在 C# 中克隆通用列表” 来自 StackOverflow 的讨论如何制作列表的深层副本。

C# just does a shallow copy when it passes by value unless the object in question executes ICloneable (which apparently the List class does not).

What this means is that it copies the List itself, but the references to the objects inside the list remain the same; that is, the pointers continue to reference the same objects as the original List.

If you change the values of the things your new List references, you change the original List also (since it is referencing the same objects). However, you then change what myList references entirely, to a new List, and now only the original List is referencing those integers.

Read the Passing Reference-Type Parameters section from this MSDN article on "Passing Parameters" for more information.

"How do I Clone a Generic List in C#" from StackOverflow talks about how to make a deep copy of a List.

我纯我任性 2024-10-12 06:49:29

虽然我同意上面大家所说的。我对这段代码有不同的看法。
基本上,您将新列表分配给局部变量 myList 而不是全局变量。
如果将 ChangeList(List myList) 的签名更改为 private void ChangeList(),您将看到 3, 4 的输出。

这是我的推理...
即使列表是通过引用传递的,也可以将其视为按值传递指针变量
当您调用 ChangeList(myList) 时,您将指针传递给(全局)myList。现在它存储在(本地)myList 变量中。所以现在你的 (local)myList 和 (global)myList 指向同一个列表。
现在你进行排序 =>它起作用是因为 (local)myList 引用原始 (global)myList
接下来,您创建一个新列表并将指针分配给您的(本地)myList。但一旦函数退出,(本地)myList 变量就会被销毁。
华泰

class Test
{
    List<int> myList = new List<int>();
    public void TestMethod()
    {

        myList.Add(100);
        myList.Add(50);
        myList.Add(10);

        ChangeList();

        foreach (int i in myList)
        {
            Console.WriteLine(i);
        }
    }

    private void ChangeList()
    {
        myList.Sort();

        List<int> myList2 = new List<int>();
        myList2.Add(3);
        myList2.Add(4);

        myList = myList2;
    }
}

While I agree with what everyone has said above. I have a different take on this code.
Basically you're assigning the new list to the local variable myList not the global.
if you change the signature of ChangeList(List myList) to private void ChangeList() you'll see the output of 3, 4.

Here's my reasoning...
Even though list is passed by reference, think of it as passing a pointer variable by value
When you call ChangeList(myList) you're passing the pointer to (Global)myList. Now this is stored in the (local)myList variable. So now your (local)myList and (global)myList are pointing to the same list.
Now you do a sort => it works because (local)myList is referencing the original (global)myList
Next you create a new list and assign the pointer to that your (local)myList. But as soon as the function exits the (local)myList variable is destroyed.
HTH

class Test
{
    List<int> myList = new List<int>();
    public void TestMethod()
    {

        myList.Add(100);
        myList.Add(50);
        myList.Add(10);

        ChangeList();

        foreach (int i in myList)
        {
            Console.WriteLine(i);
        }
    }

    private void ChangeList()
    {
        myList.Sort();

        List<int> myList2 = new List<int>();
        myList2.Add(3);
        myList2.Add(4);

        myList = myList2;
    }
}
三岁铭 2024-10-12 06:49:29

使用 ref 关键字。

查看此处的权威参考以了解传递参数。
具体来说,请查看,了解代码的行为。

编辑: Sort 适用于相同的引用(按值传递),因此值是有序的。但是,为参数分配新实例将不起作用,因为参数是按值传递的,除非您放置 ref

通过放置 ref,您可以将指针更改为对您的情况下的 List 新实例的引用。如果没有 ref,您可以处理现有参数,但无法使其指向其他参数。

Use the ref keyword.

Look at the definitive reference here to understand passing parameters.
To be specific, look at this, to understand the behavior of the code.

EDIT: Sort works on the same reference (that is passed by value) and hence the values are ordered. However, assigning a new instance to the parameter won't work because parameter is passed by value, unless you put ref.

Putting ref lets you change the pointer to the reference to a new instance of List in your case. Without ref, you can work on the existing parameter, but can't make it point to something else.

温柔嚣张 2024-10-12 06:49:29

为引用类型的对象分配了两部分内存。一种在栈中,一种在堆中。堆栈中的部分(也称为指针)包含对堆中部分的引用 - 实际值存储在堆中。

当不使用 ref 关键字时,仅创建堆栈中部分的副本并将其传递给方法 - 对堆中相同部分的引用。因此,如果您更改堆部分中的某些内容,这些更改将保留。如果您更改复制的指针 - 通过将其指定为引用堆中的其他位置 - 它不会影响方法外部的原始指针。

There are two parts of memory allocated for an object of reference type. One in stack and one in heap. The part in stack (aka a pointer) contains reference to the part in heap - where the actual values are stored.

When ref keyword is not use, just a copy of part in stack is created and passed to the method - reference to same part in heap. Therefore if you change something in heap part, those change will stayed. If you change the copied pointer - by assign it to refer to other place in heap - it will not affect to origin pointer outside of the method.

爺獨霸怡葒院 2024-10-12 06:49:28

最初,它可以用图形表示如下:

Init states

然后,应用排序 myList.Sort() ;
Sort collection

最后,当您执行以下操作时:myList' = myList2,您丢失了其中一个参考,但不是原始的,并且集合保持排序。

Lost reference

如果您通过引用使用 (ref),则 myList'myList 将变得相同(只有一个引用)。

注意:我使用 myList' 来表示您在 中使用的参数>ChangeList(因为您提供的名称与原始名称相同)

Initially, it can be represented graphically as follow:

Init states

Then, the sort is applied myList.Sort();
Sort collection

Finally, when you did: myList' = myList2, you lost the one of the reference but not the original and the collection stayed sorted.

Lost reference

If you use by reference (ref) then myList' and myList will become the same (only one reference).

Note: I use myList' to represent the parameter that you use in ChangeList (because you gave the same name as the original)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文