Не могу запустить деструктор класса с#
Помогите реализовать деструктор – не пойму, как сослаться на него:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Laba6
{
class EngMoney
{
private float funt, pens, shilling,funt1,pens1,shilling1,nomer;
private bool vuvod;
public EngMoney(float funt, float pens, float shilling, float funt1, float pens1, float
shilling1, int nomer)
{
if (nomer == 1)
{
this.funt = funt + funt1;
this.pens = pens + pens1;
this.shilling = shilling+shilling1;
}
if (nomer == 2)
{
this.funt = funt - funt1;
this.pens = pens - pens1;
this.shilling = shilling - shilling1;
}
if (nomer == 3)
{
this.funt = funt * funt1;
this.pens = pens * pens1;
this.shilling = shilling * shilling1;
}
if (nomer == 4)
{
this.funt = funt / funt1;
this.pens = pens / pens1;
this.shilling = shilling / shilling1;
}
if (nomer == 5)
{
shilling = funt * 12 * 20;
shilling1 = funt1 * 12 * 20;
if (shilling > shilling1)
{
vuvod = false;
}
if (shilling < shilling1)
{
vuvod = true;
}
}
this.funt1 = funt1;
this.pens1 = pens1;
this.shilling1 = shilling1;
this.nomer = nomer;
}
public void Print()
{
if (nomer == 5)
{
if (vuvod == false)
{
Console.WriteLine("Первая сумма больше");
}
if (vuvod == true)
{
Console.WriteLine("Вторая сумма больше первой");
}
EngMoney();
}
else
{
Console.WriteLine("funt: " + funt);
Console.WriteLine("pens :" + pens);
Console.WriteLine("shilling: " + shilling);
}
}
~EngMoney()
{
Console.Beep();
Console.WriteLine("Disposed");
}
}
class Program
{
public static float f, p, s,f1,p1,s1;
public static int nomer;
static void Main(string[] args)
{
Console.WriteLine("Ввод первой суммы");
Console.WriteLine("Введите фунты: ");
f = float.Parse(Console.ReadLine());
Console.WriteLine("Введите пенсы: ");
p = float.Parse(Console.ReadLine());
Console.WriteLine("Введите шилинги: ");
s = float.Parse(Console.ReadLine());
Console.WriteLine("Ввод второй суммы");
Console.WriteLine("Введите фунты: ");
f1 = float.Parse(Console.ReadLine());
Console.WriteLine("Введите пенсы: ");
p1 = float.Parse(Console.ReadLine());
Console.WriteLine("Введите шилинги: ");
s1 = float.Parse(Console.ReadLine());
Console.WriteLine("Выберите действие:");
Console.WriteLine("1. Сложение");
Console.WriteLine("2. Вычитание");
Console.WriteLine("3. Умножение");
Console.WriteLine("4. Деление");
Console.WriteLine("5. Сравнение");
nomer = int.Parse(Console.ReadLine());
EngMoney newValue = new EngMoney(f, p, s, f1, p1, s1,nomer);
newValue.Print();
Console.ReadLine();
}
}
}
Ответы (1 шт):
В C# это не деструктор, а финализер, вызов финализера - на усмотрение Garbage Collector. Все что вам нужно - это посмотреть примеры реализации и унаследовать
IDisposableинтерфейс.
Дополню комментарии выше примером. Просто в IDisposable финализатор есть, и программист его как бы не использует, то есть финализатор предназначен для GC, который может вызвать его, может не вызвать. И это вызывало километровые ленты обсуждений на гитхабе, нет ясности и конкретности в том, будет вызван финализатор, или нет. И есть конкретный ответ: "Финализатор обязательно будет вызван, но это не точно.", вот например неплохой блог пост на эту тему.
Я написал небольшой пример, который все-таки создает условия для вызова финализатора.
public class Program
{
static void Main(string[] args)
{
ConstructObjects();
Console.WriteLine("[main] GC Collecting");
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("[main] Done");
Console.ReadKey();
}
private static void ConstructObjects()
{
Console.WriteLine("[main] Constructing");
MyDisposable m = new MyDisposable(0);
new MyDisposable(1);
Console.WriteLine("[main] Disposing [object 0]");
m.Dispose();
}
}
public class MyDisposable : IDisposable
{
private int _id;
public MyDisposable(int id)
{
_id = id;
Console.WriteLine($"[object {_id}] Constructed");
}
private bool disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
Console.WriteLine($"[object {_id}] Disposing by Dispose()");
}
else
{
Console.WriteLine($"[object {_id}] Disposing by ~Finalizer");
}
Console.WriteLine($"[object {_id}] Disposed");
disposed = true;
}
else
Console.WriteLine($"[object {_id}] Already disposed!");
}
~MyDisposable()
{
Dispose(false);
}
}
А вывод в консоль вот такой
[main] Constructing
[object 0] Constructed
[object 1] Constructed
[main] Disposing [object 0]
[object 0] Disposing by Dispose()
[object 0] Disposed
[main] GC Collecting
[object 1] Disposing by ~Finalizer
[object 1] Disposed
[main] Done
Спасибо @Uranus за дополнение, я исправил пример в этом ответе, вынес создание объекта в отдельный метод.
Я сделал такой вывод: Финализатор объекта не вызовется до тех пор, пока вы не покинете метод, в котором он был создан (или находился в зоне видимости по ссылке). Ну и само собой ссылок на этот объект на момент сборки мусора не должно существовать, иначе он не соберется.
Другими словами, если хочется гарантий, что объект будет уничтожен вовремя и правильно, надо вызвать вручную Dispose() и не париться. А GC вас прикроет, дернет финализатор потеряного объекта, если вы где-то ошиблись и забыли прибрать за собой неуправляемые ресурсы.