3

可能重复:
通过 ref 传入对象

使用下面的代码,输出将是:

Without:
With:1

代码:

    static void Main(string[] args)
    {
        var listWithoutRef = new List<int>();
        WithoutRef(listWithoutRef);
        Console.WriteLine("Without:" + string.Join(" ", listWithoutRef));

        var listWithRef = new List<int>();
        WithRef(ref listWithRef);
        Console.WriteLine("With:" + string.Join(" ", listWithRef));
    }

    static void WithoutRef(List<int> inList)
    {
        inList = new List<int>(new int[] { 1 });
    }

    static void WithRef(ref List<int> inList)
    {
        inList = new List<int>(new int[] { 1 });
    }

只看这个,我会说一个 List 在堆上,所以无论如何都是由 ref 传递的,所以它们应该是一样的?我误解了 ref 关键字吗?还是我错过了其他东西?

4

2 回答 2

7

我误解了 ref 关键字吗?还是我错过了其他东西?

是的。您不是将列表本身传递给方法,而是通过引用传递对列表的引用。这使您可以更改方法中的引用(List<int>实际listWithRef引用的),并使其反映。

如果不使用ref关键字,您的方法就无法更改对列表的引用 - 在任何一种情况下,实际的列表存储机制都不会改变。

请注意,如果您只想使用列表,则不需要这样做。例如,您可以List<int>.Add在任一方法中调用,列表将添加新项目。只有引用类型需要 Ref 才能更改引用本身。

于 2012-06-26T18:28:08.253 回答
3

是的,所有List对象都存储在堆上。但是,没有ref关键字,您无法重新分配inList参数并使其影响调用者的范围。当您创建一个新List对象时,它会作为一个新对象进入堆中,但调用者范围内的原始引用不受影响,除非您使用ref关键字。

WithoutRef中,如果您在现有的上调用方法List而不重新定义它,您将看到它已被修改:

inList.Clear();
inList.Add(1);
于 2012-06-26T18:28:06.503 回答