// IDisposable. public sealed class ErrorList : IDisposable { private string category; private List<string> errors; public ErrorList(string category) { this.category = category; this.errors = new List<string>(); } // ( / ) // public void Dispose() { if (this.errors != null) { this.errors.Clear(); this.errors = null; } } }
// IDisposable. public sealed class ErrorList : IDisposable { private string category; private List<string> errors; public ErrorList(string category) { this.category = category; this.errors = new List<string>(); } // ( / ) // public void Dispose() { if (this.errors != null) { this.errors.Clear(); this.errors = null; } } ~ErrorList() { // !</font> // !</font> this.Dispose(); } }
// IDisposable. public sealed class ErrorList { private string category; private List<string> errors; public ErrorList(string category) { this.category = category; this.errors = new List<string>(); } }
// . public sealed class SingleApplicationInstance { 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; } } ~SingleApplicationInstance() { // , , !!! this.namedMutex.Close(); } }
// IDisposable. 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() { if (namedMutex != null) { namedMutex.Close(); namedMutex = null; } } }
// IDisposable. 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(); } }
Note: The presence of such complex official documentation on IDisposable is due to the fact that Microsoft believes that your class will contain both types of resources. This is a retention of .NET 1.0, left for backwards compatibility. Even classes written by Microsoft do not follow this old pattern (they were modified in .NET 2.0 using the pattern described in this article). FxCop will say that you need to “correctly” implement IDisposable (that is, use the old template). Do not listen to him - FxCop is mistaken.
// IDisposable. // SafeHandle. 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); }
Note: the above solution is the simplest and has its drawbacks. For example, if a thread ends immediately after performing the resource allocation function, then this resource may leak. If you are packing an IntPtr handle, it is best to inherit from the SafeHandle class. If you need to go further and maintain a reliable release of resources, then everything quickly becomes very confusing ( one more good article - note. )!
Source: https://habr.com/ru/post/89720/
All Articles