理解作为值传递的引用

时间:2018-01-31 13:12:26

标签: c# c#-4.0

我对这段代码很困惑。即使我也阅读了@John Skeet的博客http://jonskeet.uk/csharp/references.html,我仍然对最后一篇文章感到有些困惑。图表表示将非常有用。

    static void Main(string[] args)
    {
        List<int> myList = new List<int>();
        myList.Add(100);
        myList.Add(50);
        myList.Add(10);
        ChangeList(myList);

        foreach (var item in myList)
        {
            Console.WriteLine(item);
        }

        Console.ReadLine();
    }

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

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

        myList = myList2;
    }

为什么输出是10,50和100.最后一行发生了什么myList = myList2;为什么无论我评论该行,还是取消注释输出仍然保持不变。

2 个答案:

答案 0 :(得分:4)

最后一行实际上没有效果,因为myList只是一个包含对实际列表的引用的变量。该变量本身是 - 作为 C#中的每个参数 - 通过值传递给方法,对其进行任何更改 该方法无效< em>在来电者上。这与为方法提供int完全相同:

void DoSomething(int a)
{
    a = 3
}

调用DoSomething(myInt)之类的方法不会更改myInt的值,因为数字是按值传递的。在您的示例中,引用只是一个数字(或更准确地说是内存地址)。在您的方法中更改该地址对外部没有影响。

通过撰写myList = myList2,您可以指定一个与初始无关的新参考

要实现这一目标,您需要ref-keyword

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

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

    myList = myList2;
}

现在这样称呼:

ChangeList(ref myList);

答案 1 :(得分:0)

所以List<T>是引用类型。这意味着myList拥有一个指向此List<int>对象的存储位置的引用。现在您调用ChangeList(List<int> myList),然后您可能会认为myList已更改。

但实际上,您已将myList的本地副本作为方法参数传递给ChangeList。因此,您更改了myList的本地副本的项目,该副本仅存在于ChangeList()方法中。

通过将ref添加到方法参数中,您不会传递myList的副本,而是将引用传递给对象,因此两个List<int>对象现在都指向同一个对象在存储上。因此,myListMain()项的值会发生变化,因为它们都引用相同的List<int>

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

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

    myList = myList2;
}

现在您必须使用ref关键字调用该方法。

ChangeList(ref myList);