Каков жизненный цикл объекта .NET?

Каков жизненный цикл объекта для объекта в .NET?

Из того, что я понимаю, это:

  • Объект создан - вызванный конструктор (если он существует)
  • Используемые методы/свойства/поля
  • Объект уничтожен - Dispose вызываемый (если он существует)
  • Деструктор, вызываемый GC в некоторой точке

Ответы

Ответ 1

Dispose не вызывается автоматически; вам нужно вызвать его или использовать используемый блок, например.

using(Stream s = File.OpenRead(@"c:\temp\somefile.txt"))
    // Do something with s

Финализатор только вызывается GC, если он существует. Наличие финализатора заставляет ваш класс собираться за 2 шага; сначала объект помещается в очередь финализатора, затем вызывается финализатор и объект собирается. Объекты без финализаторов напрямую собираются.

Руководством является то, что Dispose избавляется от управляемых и неуправляемых ресурсов, а финализатор только очищает неуправляемые ресурсы. Когда метод Dispose освободил неуправляемые ресурсы, он может вызвать GC.SuppressFinalize, чтобы объект не жил долго, чтобы его помещали в очередь финализатора. См. MSDN для правильного образца шаблона удаления.

Ответ 2

Так же, как и кромка края... вы можете создавать объекты без использования ctor вообще:

class Foo {  
    public Foo() {
        message += "; ctor";
    }
    string message = "init";
    public string Message { get { return message; } }
}
static class Program {
    static void Main() {
        Foo foo = new Foo();
        Console.WriteLine(foo.Message); // "init; ctor"
        Foo bar = (Foo)System.Runtime.Serialization.FormatterServices
            .GetSafeUninitializedObject(typeof(Foo));
        Console.WriteLine(bar.Message); // null
    }
}

Ответ 3

Вот шаги, которые я знаю:

  • загрузить сборку
  • выполнить статические инициализаторы
  • "новый" вызов:
    • выделить память
    • выполнить нестатические инициализаторы
    • выполнить конструктор
  • экземпляр теперь готов к использованию
  • после того, как последняя ссылка на объект исчезла: если объект не имеет финализатора, он теперь готов к сборке; если объект имеет финализатор, он помещается в очередь финализатора.
  • (необязательно) объекты из очереди финализатора имеют свой финализатор, вызываемый в специальном потоке; если по-прежнему нет ссылки из приложения на объект, он также становится теперь подходящим для сбора мусора.
  • сборщик мусора освобождает память

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

Ответ 4

Здесь - подробный описатель вопроса. Во-первых, Dispose не вызывается во время выполнения, вы должны называть его самостоятельно. Также нет деструкторов, но финализаторы: если объект переопределяет метод Finalized, он вызывается, когда объект больше не доступен для приложения. Может случиться так, что при завершении объект снова становится доступным (например, сохраняет ссылку на себя в глобальном объекте), поэтому он возвращается к шагу 2 вашей модели. Существуют также методы в объекте GC, которые позволяют пользователю контролировать завершение объекта.

Ответ 5

Точка о конструкторе:

Каждый класс имеет один, поскольку один будет сгенерирован компилятором, если вы его не закодируете сами. И первое, что это делает (если не указано иное), - это вызов ctor этого родительского типа.

Ответ 6

0) Если Static Constructor существует в Object, он вызывается в первый раз, и объект этого типа создается или ссылается

Ответ 7

Вот примерный класс, который использует всю информацию, доступную в приведенных здесь статьях. Я уже много часов тестировал, и это самое лучшее для меня.

/*********************************
 * Author:  Theofanis Pantelides *
 *   Date:  23 Jun 2009          *
 *********************************/

using System;
using System.IO;

public class MyClass : IDisposable
{
    String oFile;
    Stream oStream;

    public MyClass(String _File)
    {
        oStream = File.OpenRead(oFile = _File);
        // Initialize
    }

    ~MyClass()
    {
        this.Dispose();
        // Destruct
    }

    public void doSomething()
    {
        // do Whatever it is you are trying to do
    }

    #region IDisposable Members

    /// <summary>
    /// Dispose all resources used by instance of class
    /// and update Garbage Collector information
    /// </summary>
    public void Dispose()
    {
        if (oStream != null)
        {
            oStream.Dispose(); // Dispose using built in functions
            GC.SuppressFinalize(oStream); // No need for Garbage Collector
        }

        oStream = null;  // Nullify it.
    }

    #endregion
}

Использование:

using(MyClass mc = new MyClass(@"c:\temp\somefile.txt"))
{
  mc.doSomething();
}

Вы даже можете использовать одно и то же объявление дважды, поскольку оно не существует вне "использования".

using(MyClass mc = new MyClass(@"c:\temp\somefile.txt"))
{
  mc.doSomething();
}

using(MyClass mc = new MyClass(@"c:\temp\somefile.txt"))
{
  mc.doSomething();
}

Ответ 8

Жизненный цикл объекта

Создание объекта. Для создания нового объекта используется ключевое слово новое.

  • Выделен блок памяти. Этот блок памяти достаточно велик, чтобы удерживать объект. (CLR обрабатывает выделение памяти для управляемых объектов)
  • Блок памяти преобразуется в объект. Объект инициализируется. (Вы можете управлять этим шагом, выполнив конструктор)

Уничтожение объекта. Вы используете уничтожение для восстановления любых ресурсов, используемых этим объектом.

  • Объект очищается; например, путем выпуска любых неуправляемых ресурсов, используемых приложением, таких как дескрипторы файлов и подключения к базе данных. (Вы можете управлять этим шагом, внедряя деструктор.)
  • Память, используемая объектом, исправлена.

CLR обрабатывает выпуск памяти, используемой управляемыми объектами; однако, если вы используете неуправляемые объекты, вам может потребоваться вручную освободить память, используемую этими элементами.

Ответ 10

В С# инициализаторы членов вызывается перед конструктором в VB.NET, они вызывается после конструктора.

Время выполнения не гарантирует вызов Finalize вообще.

Dispose и Finalize предназначен только для очистки неуправляемых ресурсов. Попытка очистки управляемых ресурсов в финализаторе, например. вызов Dispose на внутренних членах приведет вас к беде, потому что они, возможно, уже были завершены.

Мне нравится держать вещи простыми и просто использовать финализатор для обнаружения и регистрации неприятного сообщения об ошибке, указывающего разработчику исправить код. Попытка выяснить, является ли безопасным выполнение работы Dispose, как предполагалось, слишком легко ошибаться и обычно не стоит проводить циклы.