字符串、引用和垃圾收集
本文关键字:引用 字符串 | 更新日期: 2023-09-27 18:07:53
假设您有一个对象,它有几个属性。其中一个属性是字符串:
private class MyObject
{
public string PropertyOne {get; set;}
...
}
我现在基于MyObject
上的内容创建一个新对象:
private class MySecondObject
{
public string PropertyOneCopy {get; set;}
public MySecondObject(MyObject myObject)
{
this.PropertyOneCopy = myObject.PropertyOne;
....
}
}
在调用场景中,我们有:
private class Scenario
{
private MySecondObject _mySecondObject;
public void Go()
{
MyObject myObject = new MyObject();
myObject.PropertyOne = "Hello, World!";
_mySecondObject = new MySecondObject(myObject);
}
}
MyObject的原始实例现在超出了作用域。_mySecondObject是长期存在的
我的问题是....原来的MyObject会被垃圾收集吗?如果我用this.PropertyOneCopy = String.Copy(myObject.PropertyOne);
会怎么样呢?
以前在myObject
中的对象将被正常垃圾收集,因为没有未完成的引用。
仍然有一个对string
对象的引用,它曾经是myObject
的PropertyOne
属性的值,但这只会阻止字符串被回收,而不是整个MyObject
实例。
String.Copy
没有什么特别的作用,它只是作为一个构造函数,接受string
实例并创建一个重复的对象(System.String
没有这样的构造函数)。
肯定会被垃圾收集。即使你不使用String.Copy.
该字符串没有引用任何其他对象…相反,你拥有的是一个对象,它有一个对字符串的引用…对该字符串发生的操作与引用该字符串的其他对象无关。
例子:
如果你有对象A, B和C,它们都有一个像这样分配的字符串属性:
string s = "str";
A.Str = s;
B.Str = A.Str;
C.Str = B.Str;
等同于:
string s = "str";
A.Str = s;
B.Str = s;
C.Str = s;
当A不再使用时,它可以死亡,而不会影响其他对象,即使它们共享相同的字符串。
原来的MyObject会被垃圾收集吗?
是的,这里只有传出的引用。没办法瞒着GC。
"Hello, World!"
字符串是共同拥有的,只要其中一个对象是存活的,它就会保持存活。
使用GC比你想象的要容易,你几乎不需要"帮助"。
. net垃圾收集器将回收被任何引用都无法访问的对象所使用的内存。当Go
退出时,对MyObject
的引用就消失了,这使得MyObject
的实例可以进行垃圾收集。MyObject
引用的字符串在MySecondObject
中也有一个引用,这没有任何区别。
MySecondObject有一个对MyObject中的字符串的引用,而不是对MyObject-object本身的引用,因此MyObject将在您退出go函数时立即释放到GC,因此无需担心。
如果你以这种方式实现,myObject将不会被释放,直到MySecondObject被释放:
private class MySecondObject {
private MyObject myObject;
public string PropertyOneCopy {
get{
return myObject.PropertyOne;
}
}
public MySecondObject(MyObject myObject) {
myObject = myObject.PropertyOne;
....
}
}