传递给ref并实例化新对象时的堆分配

时间:2016-08-04 16:25:43

标签: c# .net

假设我有以下代码:

var person = new Person();
Manipulate(ref person);

以下方法:

public void Manipulate(ref Person pObject)
{
    pObject = new Person();
}

Manipulate方法在实例化一个新的Person对象时,指向Heap上的相同位置并在该位置创建pObject,还是在堆上创建一个新位置?

2 个答案:

答案 0 :(得分:2)

答案在Docs

  

对象的存储位置作为传递给方法   参考参数的值。如果更改了中的值   你也可以参数的存储位置(指向一个新对象)   更改呼叫者所指的存储位置。

为清楚起见,请查看以下示例:

static int[] array = new int[] { 5 };

static void Main(string[] args)
{
    var array2 = array;
    ModifyRef(ref array2);

    foreach (var item in array)
        Console.WriteLine(item);
    foreach (var item in array2)
        Console.WriteLine(item);
}

private static void ModifyRef(ref int[] array)
{
    array = new int[1];
    array[0] = 10;
}

打印:

5
10

通过引用传递指针引用新对象并不意味着替换旧对象。 array2现在指向一个新的内存位置,但array仍然指向内存中相同的旧数组。

答案 1 :(得分:2)

在某些情况下,在同一内存位置创建对象没有意义。如果发生这种情况,以下代码将无法正常工作:

public class Program
{
    static void Main(string[] args)
    {
        var x = new Person("Old name");
        var y = x;
        M(ref x);
        Console.WriteLine(y.Name); // Prints "Old name"

        Console.ReadKey();
    }

    static void M(ref Person person)
    {
        person = new Person("New name");
    }
}

class Person
{
    public string Name { get; }

    public Person(string name)
    {
        Name = name;
    }
}

具有Old name属性值的旧对象将不再存在,因此您无法看到Old name打印出来。由于您确实看到了它,因此同时存在两个不同的对象。

在你的例子中用旧的替换旧对象不会破坏任何东西,但我怀疑这样的检查是否正在执行,因为在设计这样的时候可能需要考虑很多不同的情况。特征