Что такое жизненный цикл объекта .NET? - PullRequest
14 голосов
/ 15 июня 2009

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

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

  1. Объект создан - вызван конструктор (если он существует)
  2. Методы / Свойства / Используемые поля
  3. Объект уничтожен - удаление вызвано (если оно существует)
  4. Деструктор вызван GC в какой-то момент

Ответы [ 9 ]

19 голосов
/ 15 июня 2009

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

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

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

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

17 голосов
/ 15 июня 2009

Точно так же, как крайний случай ... вы можете создавать объекты вообще без использования 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
    }
}
6 голосов
/ 15 июня 2009

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

  1. загрузить сборку
  2. Выполнить статические инициализаторы
  3. «новый» звонок:
    1. выделить память
    2. выполнить нестатические инициализаторы
    3. выполнить конструктор
  4. экземпляр теперь готов к использованию
  5. после того, как исчезла последняя ссылка на объект: если у объекта нет финализатора, он теперь готов к сбору; если объект имеет финализатор, он помещается в очередь финализаторов.
  6. (необязательно) объекты из очереди финализатора имеют свой финализатор, вызываемый в специальном потоке; если из приложения до сих пор нет ссылки на объект, теперь он также становится пригодным для сборки мусора
  7. сборщик мусора освобождает память

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

5 голосов
/ 15 июня 2009

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

1 голос
/ 29 июля 2014

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

Создание объекта : Вы используете ключевое слово new для создания экземпляра нового объекта.

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

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

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

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

1 голос
/ 23 июня 2009

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

/*********************************
 * 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();
}
1 голос
/ 18 июня 2009

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

1 голос
/ 15 июня 2009

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

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

0 голосов
/ 22 июня 2009

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

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

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

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

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