Строки, ссылки и сборка мусора - PullRequest
2 голосов
/ 05 сентября 2011

Представьте, что у вас есть объект, обладающий несколькими свойствами.Одним из этих свойств является строка:

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);?

Ответы [ 5 ]

3 голосов
/ 05 сентября 2011

Объект, который раньше находился в myObject, будет собираться мусором в обычном порядке, поскольку на него нет невыполненных ссылок.

Все еще существует ссылка на объект string, который раньшезначение PropertyOne свойства myObject, но это только предотвратит восстановление строки , а не всего экземпляра MyObject.

String.Copy не делает ничего особенного,он просто служит конструктором, который принимает экземпляр string и создает дубликат объекта (System.String не имеет такого конструктора).

2 голосов
/ 05 сентября 2011

Это будет сбор мусора наверняка. Даже если вы не используете 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 больше не используется, он может умереть, не влияя на другие объекты, даже если они разделяют одну и ту же строку.

1 голос
/ 05 сентября 2011

будет ли когда-нибудь исходный MyObject собираться мусором?

Да, здесь есть только исходящие ссылки.Нечего скрывать от ГК.

Строка "Hello, World!" находится в совместном владении и будет оставаться в живых до тех пор, пока жив один из объектов.

Использование ГХ проще, чем вы думаете, вам почти никогда не придется «помогать».

0 голосов
/ 05 сентября 2011

MySecondObject имеет ссылку на строку в MyObject, а не на сам объект MyObject, поэтому myObject будет передан в GC, как только вы выйдете из функции Go, поэтому не нужно беспокоиться.

Если бы вместо этого вы реализовали таким образом, myObject не был бы выпущен, пока не будет выпущен MySecondObject:

private class MySecondObject {

    private MyObject myObject;

    public string PropertyOneCopy {
        get{
            return myObject.PropertyOne;
        }
    }

    public MySecondObject(MyObject myObject)     {
        myObject = myObject.PropertyOne;
        ....
    }
}
0 голосов
/ 05 сентября 2011

Сборщик мусора .NET восстановит память, используемую объектами, которые больше не доступны ни по каким ссылкам. Ссылка на MyObject исчезает, когда Go завершает работу, делая экземпляр MyObject eligble для сборки мусора. То, что MyObject ссылается на строку, в которой также есть ссылка, хранящаяся в MySecondObject, не имеет значения.

...