C# 返回值内存范围

C# 返回值内存范围,c#,memory,garbage-collection,return-value,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.ID = 3; Console.WriteLine(obj1.ID); // => 3 obj2只是内存中对obj1的引用,还是将其

如果我有如下方法:

public SomeObject GetObject(int ID){

    SomeObject obj1 = new SomeObject();

    obj1.ID = ID;

    return obj1;
}
那么如果我使用这样的方法:

SomeObject obj2 = GetObject(4);
obj2.ID = 3;
Console.WriteLine(obj1.ID); // => 3
obj2
只是内存中对
obj1
的引用,还是将其复制到内存中并存在两个完整的对象


如果后者为真,GC什么时候从内存中删除obj1?

取决于类型。有值类型和引用类型

将值本身存储在内存中,每次传递它时,都只是复制值(即值类型),除非使用类似于
公共无效测试(ref int x)
的方法。ref存在的事实意味着通过引用传递整数

当你有一个(对象)变量时,你基本上只是抓住一个指针。因此它将传递对象的相同引用

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

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

当对象不再有任何引用时,obj1(或对象本身,因为obj1只是一个引用)将被GC'd。

它将是内存中对
obj1
的引用,假设
obj1
而不是
结构

如果某个对象是引用类型,那么您将获得引用副本,如果某个对象是值类型,那么您将获得副本,这是正确的。垃圾收集器会在稍后某个时候清理某个对象,当它决定释放内存时。但是,您可以通过调用GC.collect来强制执行GC hand,如果某个对象从中删除,则位于GetObject作用域中的实例将在返回后立即销毁,并将创建一个新实例并分配给obj2。 如果SomeObject不是ValueType,也就是引用类型,那么只返回它的引用,所以最终只返回一个实例。
无法预测GC何时销毁对象,但是,GC只销毁引用类型,当代码执行超出其范围时,ValueType会自动销毁。

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;
}

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

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


在讨论引用类型时,记住对象实例、实例引用和保存引用的变量之间的区别很重要。变量
obj1
保存对实例的引用,并且该变量在方法的堆栈框架中分配,因此当您退出该方法时,该变量将消失。引用是从方法返回的,但此时变量不再存在。

对象实际上不是“按值”传递的。它们的引用是按值传递的。@minitech我不确定我是否说过它们不是,但这只是让人困惑,因为问题是对象的内容是否被复制,而您的示例与此无关。