जब हमें अनमैनेज्ड ऑब्जेक्ट्स को डिस्पोज़ करने की आवश्यकता होती है तो हमें IDisposable डिज़ाइन पैटर्न (या डिस्पोज़ पैटर्न) का उपयोग करना चाहिए।
IDisposable डिज़ाइन पैटर्न को लागू करने के लिए, वह क्लास जो अनमैनेज्ड ऑब्जेक्ट्स से सीधे या अप्रत्यक्ष रूप से निपटती है, को IDisposable इंटरफेस को लागू करना चाहिए और IDisposable इंटरफेस के अंदर घोषित Dispose मेथड को लागू करना चाहिए। हम सीधे अनमैनेज्ड ऑब्जेक्ट्स से नहीं निपटते। लेकिन हम मैनेज्ड क्लासेस से निपटते हैं, जो सीधे अनमैनेज्ड ऑब्जेक्ट्स से निपटते हैं। उदाहरण: फाइल हैंडलर्स, कनेक्शन स्ट्रिंग्स, HTTP स्ट्रीम्स, आदि।
इस पैटर्न का एक महत्वपूर्ण पहलू यह है कि यह विरासत में मिली क्लासेस के लिए IDisposable डिज़ाइन पैटर्न का पालन करना आसान बनाता है। और यह एक ओवरराइडेबल Dispose मेथड के कार्यान्वयन के कारण है। यह पैटर्न फाइनलाइज़र मेथड (या C# में डिस्ट्रक्टर) के उपयोग का भी सुझाव देता है। हालांकि, यदि हम फाइनलाइज़र का उपयोग करते हैं, तो इसके प्रदर्शन निहितार्थों के कारण इसे ठीक से प्रबंधित किया जाना चाहिए।
पूर्ण IDisposable पैटर्न कार्यान्वयन
using System;
using System.Net.Http;
public class ServiceProxy : IDisposable
{
private readonly HttpClient _httpClient;
private bool _disposed = false;
public ServiceProxy(IHttpClientFactory httpClientFactory)
{
_httpClient = httpClientFactory.CreateClient();
}
// फाइनलाइज़र (डिस्ट्रक्टर) - केवल अनमैनेज्ड संसाधन होने पर आवश्यक
~ServiceProxy()
{
Dispose(false);
}
// पब्लिक Dispose मेथड
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this); // फाइनलाइज़र को कॉल होने से रोकता है
}
// प्रोटेक्टेड वर्चुअल Dispose - विरासत के लिए अनुमति देता है
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing)
{
// मैनेज्ड संसाधन डिस्पोज़ करें
_httpClient?.Dispose();
}
// अनमैनेज्ड संसाधन यहां डिस्पोज़ करें (यदि कोई हो)
// उदाहरण: Marshal.FreeHGlobal(unmanagedPtr);
_disposed = true;
}
public async Task<HttpResponseMessage> GetAsync(string url)
{
return await _httpClient.GetAsync(url);
}
public async Task<HttpResponseMessage> PostAsync(string url, StringContent content)
{
return await _httpClient.PostAsync(url, content);
}
}
उपयोग: using स्टेटमेंट के साथ
static async Task Main(string[] args)
{
using var serviceProxy = new ServiceProxy(httpClientFactory);
var response = await serviceProxy.GetAsync("https://api.example.com/data");
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(content);
// स्वचालित रूप से Dispose() कॉल होता है यहां
}
पैटर्न के मुख्य घटक
| घटक | उद्देश्य |
|---|---|
IDisposable इंटरफेस | कॉन्ट्रैक्ट परिभाषित करता है |
Dispose() (पब्लिक) | निर्धारक सफाई, GC.SuppressFinalize कॉल करता है |
Dispose(bool) (प्रोटेक्टेड वर्चुअल) | वास्तविक सफाई तर्क, विरासत की अनुमति देता है |
~Finalizer() | सुरक्षा जाल यदि Dispose नहीं कॉल किया गया |
_disposed फ्लैग | डबल-डिस्पोज़ रोकता है |
विरासत में मिली क्लास के लिए पैटर्न
public class DerivedService : ServiceProxy
{
private readonly MemoryStream _stream = new MemoryStream();
private bool _disposed = false;
protected override void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing)
{
_stream?.Dispose(); // अपने मैनेज्ड संसाधन डिस्पोज़ करें
}
// अपने अनमैनेज्ड संसाधन डिस्पोज़ करें
_disposed = true;
base.Dispose(disposing); // बेस Dispose कॉल करें!
}
}
सर्वोत्तम अभ्यास
- हमेशा
usingस्टेटमेंट याawait using(IAsyncDisposable के लिए) का उपयोग करें - यदि कोई अनमैनेज्ड संसाधन नहीं है तो फाइनलाइज़र न लिखें
Dispose(bool)कोprotected virtualबनाएं विरासत के लिएGC.SuppressFinalize(this)कॉल करें जब मैन्युअली डिस्पोज़ कर रहे हों_disposedफ्लैग के साथ आइडेम्पोटेंट बनाएं
.NET Core 3.0+: IAsyncDisposable
public class AsyncService : IAsyncDisposable
{
private readonly HttpClient _client = new HttpClient();
public async ValueTask DisposeAsync()
{
await _client.DisposeAsync();
}
}
// उपयोग
await using var service = new AsyncService();