2011-04-21 74 views
3

如果我有一个方法,如:返回值存储器范围

public SomeObject GetObject(int ID){ 

    SomeObject obj1 = new SomeObject(); 

    obj1.ID = ID; 

    return obj1; 
} 

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

SomeObject obj2 = GetObject(4); 

威尔obj2简单地是obj1在存储器中的参考,或将它被复制到内存中并存在两个完整的对象?

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

回答

5

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

Value types将值本身存储在内存中,每次将值传递给它时,只需复制值(因此,值类型),除非使用类似public void Test(ref int x)之类的值。 ref有这个意思是通过引用传递整数。

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

您可以通过扩展您的代码做这样的事情证实了这一点:

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

OBJ1(或对象本身,因为OBJ1只是一个参考)将GC'd时不再有任何引用到物体。

1

obj1的存储器中,这将是一个参考,假设obj1class而不是struct

0

如果某个对象是一个引用类型,那么你会得到一个引用副本,如果SomeObject是一个值类型,你会得到一个副本。垃圾收集器会在稍后决定释放内存时清理SomeObject。但是,您可以通过调用GC强制执行GC手。收集

3

如果SomeObject从ValueType延迟,那么位于GetObject作用域中的实例将在其返回时立即销毁并创建新实例并将其分配给obj2。 如果SomeObject不是一个ValueType,也就是引用类型,那么只有它的引用将被返回,所以你最终得到1个实例。 不可能预测GC何时会销毁一个对象,但是,GC只会销毁引用类型,当代码执行超出其范围时,ValueType会自动销毁。

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

对象实际上并未“按价值”传递。他们的引用是通过价值传递的。 – Ryan 2011-05-16 18:03:20

+0

@minitech我不确定我说他们不是 – 2011-05-16 19:51:45

+0

但这只是令人困惑,因为问题是询问对象的内容是否被复制,而您的示例与此无关。 – Ryan 2011-05-16 22:28:03

2

假设SomeObject是一个类,该方法将一个参考返回到对象实例,它创建。

对象实例不会被复制,只有一个实例。在。除非您特别要求复制,例如通过调用Clone方法,否则不会复制任何对象。

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