Как убить экземпляр класса?
От: Vyacheslav_M  
Дата: 24.07.02 16:45
Оценка:
Привет всем!

Есть следующий код

public class MessageBox : System.Windows.Forms.Form
{
...
    private static MessageBox instance;
    
    public static void Show(string message,string title)
    {
        if(instance==null)instance=new MessageBox(message,title);
    }

    public MessageBox(string message,string title)
    {
        InitializeComponent();
        this.lblMessage.Text=message;
        this.ShowDialog();
    }

    ~MessageBox()
    {
        System.Windows.Forms.MessageBox.Show("Деструктор","");
    }

    private void cmdOk_Click(object sender, System.EventArgs e)
    {
        instance=null;
        this.Close();    
    }
...
}


public class frmMain : System.Windows.Forms.Form
{
...
    private void cmdShowMessage(object sender, System.EventArgs e)
    {
        MessageBox.Show("Message1","");
        MessageBox.Show("Message2"."");
    }
...


При запуске увидим Message1 и никогда не увидим Message2, а Деструктор вызовется только при завершении приложения. Почему? Ведь при нажатии кнопки cmdOk окно закрывается а переменной instance присваивается null, значит ссылок на обьект больше нет и обьект должен уничтожится.
Почему этого не происходит?
Re: Как убить экземпляр класса?
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 24.07.02 17:41
Оценка:
Здравствуйте Vyacheslav_M, Вы писали:

VM>При запуске увидим Message1 и никогда не увидим Message2, а Деструктор вызовется только при завершении приложения. Почему? Ведь при нажатии кнопки cmdOk окно закрывается а переменной instance присваивается null, значит ссылок на обьект больше нет и обьект должен уничтожится.

VM>Почему этого не происходит?
Потому что GC запускается не сразу а когда время есть. Вставь после первого вызова GC.Collect(). Но, честно говоря, зачем такой извращенный дизайн я не понял.
AVK Blog
Re[2]: Как убить экземпляр класса?
От: Mishka.NET Норвегия  
Дата: 25.07.02 07:22
Оценка:
Здравствуйте AndrewVK, Вы писали:

AVK>Потому что GC запускается не сразу а когда время есть. Вставь после первого вызова GC.Collect(). Но, честно говоря, зачем такой извращенный дизайн я не понял.


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

Да, и деструкторы вообще лучше не использовать, вместо них надо переопределять Finalize(). В 1 номере журнала RSDN это всё будет популярно объяснено.
Re[3]: Как убить экземпляр класса?
От: Silver_s Ниоткуда  
Дата: 25.07.02 15:01
Оценка:
Здравствуйте Mishka.NET, Вы писали:

M.NET>Да, и деструкторы вообще лучше не использовать, вместо них надо переопределять Finalize(). В 1 номере журнала RSDN это всё будет популярно объяснено.


А это разве уже не устаревший подход Finalize переопределять? Это Beta так было.
Либо я чего то не понял, либо ...
Каким образом Finalize переопределять... ?

Если пишем так, compiler выдает ошибку
class A
{
    protected override void Finalize(){}

}

Error(503): Do not override object.Finalize. Instead, provide a destructor.


Да и в стандарте такие вещи пишут:
~MyClass() 
{
   // Cleanup statements.
}
The destructor implicitly calls the Object.Finalize method on the object's base class. Therefore, the preceding destructor code is implicitly translated to:
protected override void Finalize()
{
   try
   {
      // Cleanup statements.
   }
   finally
   {
      base.Finalize();
   }
}



This means that the Finalize method is called recursively for all of the instances in the inheritance chain, 
from the most derived to the least derived.

.....

Destructors are implemented by overriding the virtual method Finalize on System.
Object. C# programs are not permitted to override this method or call it (or overrides of it) directly.
Re[4]: Как убить экземпляр класса?
От: Mishka.NET Норвегия  
Дата: 25.07.02 15:14
Оценка:
Здравствуйте Silver_s, Вы писали:

SS>Destructors are implemented by overriding the virtual method Finalize on System.

SS>Object. C# programs are not permitted to override this method or call it (or overrides of it) directly.

Этого я не знал. Но что знаю точно, так это то, что никогда деструкторы писать не буду. Практически не осталось задач, в которых это требовалось бы. Если надо освобождать ресурсы, то класс должен реализовывать интерфейс IDisposable, и соответственно в функции Dispose всё что надо освобождать. При этом для удобства советуют использовать оператор using. Но как не крути ресурсы, которые не память, придётся освобождать РУКАМИ. И GC тут не поможет.
Re[5]: Как убить экземпляр класса?
От: Mishka.NET Норвегия  
Дата: 25.07.02 15:20
Оценка:
Здравствуйте Silver_s, Вы писали:

SS>>Destructors are implemented by overriding the virtual method Finalize on System.

SS>>Object. C# programs are not permitted to override this method or call it (or overrides of it) directly.

M.NET>Этого я не знал. Но что знаю точно, так это то, что никогда деструкторы писать не буду. Практически не осталось задач, в которых это требовалось бы. Если надо освобождать ресурсы, то класс должен реализовывать интерфейс IDisposable, и соответственно в функции Dispose всё что надо освобождать. При этом для удобства советуют использовать оператор using. Но как не крути ресурсы, которые не память, придётся освобождать РУКАМИ. И GC тут не поможет.


И ещё хочу добавить, что тот же Рихтер не советует использовать так называемые "деструкторы" в С#.
Re[2]: Как убить экземпляр класса?
От: Vyacheslav_M  
Дата: 25.07.02 18:05
Оценка:
Здравствуйте AndrewVK, Вы писали:

AVK>Потому что GC запускается не сразу а когда время есть. Вставь после первого вызова GC.Collect(). Но, честно говоря, зачем такой извращенный дизайн я не понял.



Проблема оказалась не только в этом.
При вызове Show сначала вызывается конструктор в котором выводится модальное окно
и при клике на кнопку переменной instance присваивается null но она в этот момент итак null
и только потом ей присваивается значение;

public class MessageBox : System.Windows.Forms.Form
{
...
    private static MessageBox instance;
    
    public static void Show(string message,string title)
    {
          new MessageBox(message,title);
    }

    public MessageBox(string message,string title)
    {
        InitializeComponent();
        this.lblMessage.Text=message;
        this.ShowDialog();
    }

    ~MessageBox()
    {
        System.Windows.Forms.MessageBox.Show("Деструктор","");
    }

    private void cmdOk_Click(object sender, System.EventArgs e)
    {
        this.Close();
        GC.Collect().

    }
...
}


public class frmMain : System.Windows.Forms.Form
{
...
    private void cmdShowMessage(object sender, System.EventArgs e)
    {
        MessageBox.Show("Message1","");
        MessageBox.Show("Message2"."");
    }
...


Изменение кода решило проблемму.

А деструктор мне и не нужен, я его использовал только для того чтоб узнать когда удаляется обьект.

Всем спасибо!
Re[4]: Как убить экземпляр класса?
От: IT Россия linq2db.com
Дата: 25.07.02 19:15
Оценка:
Здравствуйте Silver_s, Вы писали:

SS>Каким образом Finalize переопределять... ?


Просто пишешь деструктор и компилятор его автоматически переименовывает в Finalize.
Если нам не помогут, то мы тоже никого не пощадим.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.