Сборщик мусора не будет собирать объект, созданный с помощью - PullRequest
6 голосов
/ 06 июня 2011

Я хочу проверить ссылки на объекты, удерживаемые неправильно, и написал тест, который всегда терпел неудачу.Я упростил тест до следующего поведения:

    [Test]
    public void ScopesAreNotLeaking()
    {
        WeakReference weakRef;
        Stub scope = null;
        using (scope = new Stub())
        {
            weakRef = new WeakReference(scope);
        }
        scope = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
        Assert.That(weakRef.Target, Is.Null);
    }

Однако этот тест, который делает то же самое без использования, проходит:

    [Test]
    public void ScopesAreNotLeaking()
    {
        WeakReference weakRef;
        Stub scope = new Stub();
        weakRef = new WeakReference(scope);
        scope = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
        Assert.That(weakRef.Target, Is.Null);
    }

Используемый класс заглушки достаточно прост:

class Stub : IDisposable
{
    public void Dispose()  {}
}

Может кто-нибудь объяснить мне, что поведение или - даже лучше - есть идея, как убедиться, что объект получает мусор?

PS: потерпите меня, если был задан похожий вопросдо.Я изучил только те вопросы, в которых использует в заголовке.

Ответы [ 4 ]

5 голосов
/ 06 июня 2011

using не предназначено для принудительного сбора мусора, а для вызова утилизации.Утилизация позволяет вам освобождать ресурсы без сбора мусора, такие как дескрипторы файлов.Сборка мусора происходит, когда c # хорош и готов.

2 голосов
/ 06 июня 2011

Я подозреваю, что в операторе using может быть введен локальный код. Используйте ildasm, чтобы увидеть, все ли ссылки в функции на объект действительно очищены перед вызовом GC.Collect. Также попробуйте поместить бит использования в отдельную функцию, которая возвращает слабую ссылку.

1 голос
/ 06 июня 2011

Ваши два контрольных примера не идентичны.В конце оператора using вызывается метод Dispose ресурса, для которого не установлено значение nullВызов Dispose не обязательно вызывает деструктор.

1 голос
/ 06 июня 2011

GC mark & ​​sweep, как он используется в .NET, не является детерминированным. Даже если вызван GC.Collect(), нет гарантии, что он действительно работает.

Кроме того, условие using не имеет ничего общего со сборкой мусора. Если просто вызвать Dispose () для своего целевого объекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...