返回值内存范围

时间:2011-04-21 00:35:57

标签: c# memory garbage-collection return-value

如果我有类似的方法:

public SomeObject GetObject(int ID){

    SomeObject obj1 = new SomeObject();

    obj1.ID = ID;

    return obj1;
}

然后,如果我使用这样的方法:

SomeObject obj2 = GetObject(4);

obj2简单地作为内存中对obj1的引用,还是将其复制到内存中并存在两个完整的对象?

如果后者属实,GC何时会从内存中删除obj1

6 个答案:

答案 0 :(得分:5)

这取决于类型。有值类型和参考类型。

Value types将值本身存储在内存中,每次传递它时,只是复制值(因此,值类型),除非您使用public void Test(ref int x)之类的东西。 ref存在的事实意味着通过引用传递整数。

当你有reference type(对象)的变量时,你基本上只是抓住一个指针。所以它会传递对象的相同引用。

您可以通过扩展代码来执行以下操作来确认:

obj2.ID = 3;
Console.WriteLine(obj1.ID); // => 3

obj1(或者对象本身,因为obj1只是一个引用),当不再有对象的引用时,它将被GC。

答案 1 :(得分:3)

如果SomeObject从ValueType中删除,那么生成在GetObject范围内的实例将在返回后立即销毁,并创建一个新实例并将其分配给obj2。 如果SomeObject不是ValueType,也就是引用类型,那么只返回它的引用,所以最终得到1个实例。 无法预测GC何时会破坏对象,但是,GC只会破坏引用类型,当代码执行超出其范围时,ValueType会自动销毁。

答案 2 :(得分:2)

obj2只会在内存中引用obj1
是(假设它不是值类型)

但有一点需要注意:对象总是按参数值传递,因此如果改变了GetObject:

public class SomeObject
{
    public string Name { get; set; }
    public int ID { get; set; }
    public SomeObject() { ID = 1; Name = "test"; }
}

static void Main(string[] args)
{
    SomeObject obj1 = new SomeObject();
    GetObject(obj1, 2);

    Console.WriteLine(obj1.ID); // prints 1
    Console.Read();
}

public static void GetObject(SomeObject obj1, int id)
{
    var obj = new SomeObject();
    obj.ID = id;
    obj.Name = "";

    obj1 = obj;
}

答案 3 :(得分:2)

假设SomeObject是一个类,该方法将返回对它创建的对象实例的引用。

不会复制对象实例,只有一个实例。在.NET中,除非您特别要求创建副本,否则不会进行对象复制,例如通过调用Clone方法。

在谈论引用类型时,记住对象实例,实例引用和包含引用的变量之间的区别非常重要。变量obj1保存对实例的引用,并且变量在方法的堆栈帧中分配,因此当您退出方法时它会消失。从方法返回引用,但此时变量不再存在。

答案 4 :(得分:1)

假设obj1obj1而不是class,它将在内存中引用struct

答案 5 :(得分:0)

如果某个对象是引用类型,那么您将获得引用副本,如果SomeObject是值类型,您将获得副本。当垃圾收集器决定它想要释放内存时,垃圾收集器会稍后清理SomeObject。但是,您可以通过调用GC.collect强制GC手。