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

Ответ Ceilingfish может быть технически правильным, но он рекомендует использовать пробел в конце строки. Это подвержено ошибкам и не является хорошей практикой!

Вот как я бы это сделал:

Создайте файл settings.yaml со следующим содержимым:

---
feeds:
  :url: 'http://www.google.com'
  :label: 'default'

Это создаст следующий хеш после загрузки файла YAML:

irb(main):001:0> require 'yaml'
=> true
irb(main):002:0> YAML.load_file('settings.yaml')
=> {"feeds"=>{:url=>"http://www.google.com", :label=>"default"}}
irb(main):003:0> 

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

14
задан Robert MacLean 17 June 2009 в 10:41
поделиться

8 ответов

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

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

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

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

19
ответ дан 1 December 2019 в 06:16
поделиться

Как и в крайнем случае ... вы можете создавать объекты вообще без использования 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
    }
}
17
ответ дан 1 December 2019 в 06:16
поделиться

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

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

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

6
ответ дан 1 December 2019 в 06:16
поделиться

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

5
ответ дан 1 December 2019 в 06:16
поделиться

Замечание о конструкторе:

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

1
ответ дан 1 December 2019 в 06:16
поделиться

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

1
ответ дан 1 December 2019 в 06:16
поделиться

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

Среда выполнения не гарантирует вызова Finalize в все.

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

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

0
ответ дан 1 December 2019 в 06:16
поделиться

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

/*********************************
 * 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'.

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

using(MyClass mc = new MyClass(@"c:\temp\somefile.txt"))
{
  mc.doSomething();
}
1
ответ дан 1 December 2019 в 06:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: