There is a class A , it has 4 text fields A1, A2, A3, A4 . I want to implement the Dispose method for the class, because there is a large text in its fields, and it is used only 1 time.

Tell me, will it be enough in my case if I do this?

Dispose() { А1 = null; А2 = null; А3 = null; А4 = null; } 

Or maybe you just need to do A1 = ""?

  • four
    Do not. Dispose is not intended to help the garbage collector, but to release unmanaged resources. - Igor
  • Those. do I even release resources on their own? - Leonard Bertone
  • What resources? "Let's agree on definitions and the dispute will resolve itself." - Igor
  • @LeonardBertone in C # is a garbage collector. He does everything himself. You need to free your hands with external resources and, for example, low-level database connections or file descriptors - Mstislav Pavlov
  • 3
    @Stack is interned by default only string literals. In your answer, by the way, this was also written. - Pavel Mayorov

4 answers 4

If you do not work in your class with unmanaged resources and you do not plan to use your class with using, then you do not need to implement IDisposable. And zeroing links is also not necessary.


The Dispose method is defined in the IDisposable interface, which is used in the .NET Framework in different classes.
It is possible to look at implementation of IDisposable in source codes . (No one here will argue that in the source .NET correct implementation of this interface).
There you can also look at the comments .NET developers
On the screenshot of the page on the right - the comments of the developers, and on the left - these are links to the implementation of IDisposable in different classes.

One example implementation of IDisposable from the .NET Framework:

 class SimpleMonitor : IDisposable { public void Enter() { ++ _busyCount; } public void Dispose() { -- _busyCount; } public bool Busy { get { return _busyCount > 0; } } int _busyCount; } 

Taken here . Nothing special, this is if you do not need to work with unmanaged resources.

IMPORTANT: when working with unmanaged resources, you should use SafeHandle .
An example is here , and a brief description under the screenshot.
Read the class description in MSDN, look at the implementation in the source code , also look at the base classes. Obviously, everything is quite complicated there. Therefore, do not invent bicycles, despite the fact that some offer it with a serious look :)

enter image description here

How to use SafeHandle?

For example, you need to use the WinAPI function FindFirstFileEx to get information about the folder. The function returns HANDLE - this is an unmanaged resource, which must be freed with the help of WinAPI function FindClose .

In such a situation, the SafeHandle class must be defined

 using Microsoft.Win32.SafeHandles; class SafeHandle : SafeHandleZeroOrMinusOneIsInvalid { private SafeHandle() : base(true) { } protected override bool ReleaseHandle() { return FindClose(this.handle); } } 

And specify SafeHandle in the function definition

 static extern SafeHandle FindFirstFileEx(...) 

In our class we write

 var h = FindFirstFileEx(...); 

Thus we get a link to a special wrapper over an unmanaged resource. And even if an unexpected interruption of the flow or stack overflow, etc., occurs, the FindClose function will be called, i.e. guaranteed to be closed handle unmanaged resource.

A working example is here .

    Answering your question about zeroing links is not; you do not need to reset them, as this will not help. Moreover, in your case, you do not need the Dispose method at all. Why, read below.


    There are only two situations when it is necessary to implement IDisposable :

    • Class has IDisposable resources
    • There are unmanaged resources in the class.

    Class has IDisposable resources

    All such resources need to call the Dispose() method or its equivalent (for example, Close() ). In 99.9% of cases, such resources are not necessary, since in any case they will be collected by the garbage collector. (Zanulli can be, if these resources occupy a large amount of memory and you want to "signal" the garbage collector so that he quickly collected them. But it does not give any guarantees .)

     public sealed class SingleApplicationInstance : IDisposable { private Mutex namedMutex; private bool namedMutexCreatedNew; public SingleApplicationInstance(string applicationName) { this.namedMutex = new Mutex(false, applicationName, out namedMutexCreatedNew); } public bool AlreadyExisted { get { return !this.namedMutexCreatedNew; } } public void Dispose() { namedMutex.Close(); } } 

    There are unmanaged resources in the class.

    The implementation of Dispose() for such classes should "close" the resource (as it depends on the resource itself) and call GC.SuppressFinalize(this); . Plus, the finalizer must be implemented, in which the "closing" of the resource should be called. So it is guaranteed that the resource will be closed anyway - either by the programmer (and the finalizer will not be called), or by the garbage collector (by calling the finalizer).

     public sealed class WindowStationHandle : IDisposable { public WindowStationHandle(IntPtr handle) { this.Handle = handle; } public WindowStationHandle() : this(IntPtr.Zero) { } public bool IsInvalid { get { return (this.Handle == IntPtr.Zero); } } public IntPtr Handle { get; set; } private void CloseHandle() { if (this.IsInvalid) { return; } if (!NativeMethods.CloseWindowStation(this.Handle)) { Trace.WriteLine("CloseWindowStation: " + new Win32Exception().Message); } this.Handle = IntPtr.Zero; } public void Dispose() { this.CloseHandle(); GC.SuppressFinalize(this); } ~WindowStationHandle() { this.CloseHandle(); } } internal static partial class NativeMethods { [DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CloseWindowStation(IntPtr hWinSta); } 

    The full version of the correct application of IDisposable is in my translation to Habré.

    • For the second case, I would recommend using SafeHandle . Of its merits, SafeHandle works even if the application domain is unloaded, in addition, SafeHandle supported by P/Invoke (the window in which the uncontrollable resource is already created is gone , but its descriptor is not saved yet) - Pavel Mayorov
    • And finally - less code is obtained, since all the main features are already implemented in the base class. - Pavel Mayorov
    • @PavelMayorov yes, right. The article mentions this. And this is just a learning example. - andreycha
    • It is not mentioned in the example, therefore I am writing ... - Pavel Mayorov
    • one
      when working with unmanaged resources do not need to invent a bicycle. There is a special SafeHandle - Stack

    The IDisposable pattern is not applicable in your case, since it serves to free up external resources, not memory. The resource in this case is something that requires explicit closure - a file, a socket, a transaction. Memory in .NET does not require manual release.

    In addition to freeing resources, IDisposable often implemented only for the use of the using syntax, but this is clearly not your case.


    Memory free in .NET is handled by the garbage collector. When he decides that the memory would cost a little bit, he tracks the reachability of objects from the so-called. roots - local variables, global static fields and other ways to somehow get to the object from the code.

    Suppose you have a local variable that refers to an object of your class. The garbage collector checks reachability:

     локальная переменная → ваш объект → большая строка 

    sees that the string is being used, and does not free memory from it.

    But here you are out of the method. Or the code in the method went beyond the last mention of your variable in the code. Your object is no longer referenced from anywhere:

     ваш объект → большая строка 

    Both object and large string are unreachable. And the garbage collector calmly burns them during the next build.

    Would the link zeroing change the situation (in Dispose, or in another method)? Not at all. Zanulenie in this situation - completely unnecessary.

      Yes you can. null

      But in general, there is a possibility that this is just too much. It only makes sense to do this if these strings really affect the memory, and the object containing them lives much longer. In any case, it is strange to use dispose for this.

      By the way, it is recommended to check if dispose was called in other methods. In your case, probably in a method using these strings.