Sobes.tech
Middle

Kuo skiriasi Dispose ir Finalize metodai?

sobes.tech AI

Atsakymas iš AI

Dispose kviečiamas aiškiai kūrėjo arba vykdymo aplinkos (pvz., using) tam, kad būtų atlaisvinti nevaldomi ištekliai. Finalize (per destruktorių C#) kviečiamas šiukšlių surinkėjo, kai objektas sunaikinamas, jei jis nebuvo aiškiai atlaisvintas.

Kriterijus Dispose Finalize (per destruktorių)
Kvietimas Aiškiai nurodytas kūrėjo (using, Dispose()) Automatiškai kviečiamas šiukšlių surinkėjo
Vykdymo laikas Determinuotas Neterminuotas (priklauso nuo šiukšlių surinkėjo)
Paskirtis Atlaisvinti tiek valdomus, tiek nevaldomus išteklius Tik nevaldomų išteklių atlaisvinimas
Įgyvendinimas IDisposable sąsaja Object.Finalize metodo perrašymas (per destruktoriaus sintaksę)
Naudojimas Pirmenybė teikiama išteklių atlaisvinimo būdui Atsarginis mechanizmas nevaldomiems ištekliams atlaisvinti

Pavyzdys naudojant using (automatinis Dispose kvietimas):

// Pavyzdys naudojant `IDisposable` įgyvendinančią klasę
using (var fileStream = new System.IO.FileStream("myfile.txt", System.IO.FileMode.Open))
{
    // Darbas su failu
} // Čia automatiškai kviečiamas fileStream.Dispose()

Klasės su IDisposable ir destruktoriumi pavyzdys:

using System;

public class MyDisposableClass : IDisposable
{
    private IntPtr unmanagedResource; // Atstovauja nevaldomą išteklių
    private bool disposed = false;

    public MyDisposableClass()
    {
        // Nevaldomo ištekliaus inicijavimas
        unmanagedResource = System.Runtime.InteropServices.Marshal.AllocHGlobal(100);
        Console.WriteLine("Išteklis paskirtas.");
    }

    // `IDisposable` įgyvendinimas
    public void Dispose()
    {
        Dispose(true);
        // Slopinti finalizaciją, nes išteklius jau atlaisvintas
        GC.SuppressFinalize(this);
        Console.WriteLine("Dispose() kviečiamas.");
    }

    // Apsaugotas virtualus metodas išteklių atlaisvinimui
    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // Valdomų išteklių atlaisvinimas (jei yra)
                Console.WriteLine("Valdomų išteklių atlaisvinimas.");
            }

            // Nevaldomų išteklių atlaisvinimas
            if (unmanagedResource != IntPtr.Zero)
            {
                System.Runtime.InteropServices.Marshal.FreeHGlobal(unmanagedResource);
                unmanagedResource = IntPtr.Zero;
                Console.WriteLine("Nevaldomas išteklius atlaisvintas.");
            }

            disposed = true;
        }
    }

    // Destruktorius (finiatorius)
    ~MyDisposableClass()
    {
        Dispose(false); // Atlaisvinti tik nevaldomus išteklius
        Console.WriteLine("Finiatorius kviečiamas.");
    }
}

Dispose metodas turi būti įgyvendintas visuose klasėse, valdančiose nevaldomus išteklius (failus, tinklo ryšius, deskriptorius ir kt.). Finalize turėtų būti naudojamas kaip atsarginis būdas atlaisvinti nevaldomus išteklius, jei Dispose nebuvo iškviestas. Klasės, įgyvendinančios Finalize, turi jį slopinti Dispose(true) metu, kad išvengtų dvigubo išteklių atlaisvinimo.