نوشته شده توسط
Wily_Fox
با سلام و خسته نباشید
دوستان عزیز اگه امکانش هست منو راهنمایی کنید:
1- آیا همه کلاس هایی که تعریف می کنیم نیاز به مشتق گرفتن از IDisposable دارند؟
2- چه زمانی یک کلاس نیاز به مشتق گرفتن از IDisposable دارد؟
3- چگونه متد Dispose رو پیاده سازی کنیم؟
متشکرم
هنگامی که کلاسی توسط CLR بارگذاری می شود تمامی متد های آن به همراه تمامی متدهای کلاس پدر و متدهای پیاده سازی شده از رابط های به ارث رفته در جدولی به نام جدول متد (Method Table) درج می گردند.
حالا فرض کنید کلاسی داریم که IDisposable را پیاده سازی می کند که دارای یک متد Dispose است.
public class Test : IDisposable { public void Dispose() { Console.WriteLine("Test.Dispose"); } }
وقتی این کلاس توسط CLR بارگذاری می شود همه توابع مجازی توسعه داده شده در جدول متد ثبت می شوند که در اینجا یک متد برای رابط IDisposable ثبت می شود و یک متد جدید نیز برای کلاس Test ثبت می شود.
حالا زمانی که بخواهیم این متد را از نمونه شئ Test و یا استفاده از ارجاع رابط Dispose به مشکلی برخوریم. به مثال زیر دقت کنید :
Test obj = new Test(); obj.Dispose(); IDisposable i = obj; i.Dispose(); //output //Test.Dispose //Test.Dispose
توجه کردید که خروجی هر دو به یک صورت بود این به این خاطر است که کامپایلر C# درهنگام کامپایل این متد را بررسی می کند و متوجه می شود که خروجی، امضاء و نوع دسترسی متد جدید در شئ Test با متد متناظر در رابط IDisposable یکسان است به همین دلیل متا دیتاهای هر دو متد را ادغام می کند که در اینصورت در جدول متد فقط یک متد ثبت می گردد که هر دو به این یک متد دسترسی دارند.
پیاده سازی صریح توابع رابط یا explicit interface method implementation (EIMI) این قابلیت را فراهم می کند تا بتوان متد های مجازی توسعه یافته رابط و متد های یک شئ را از یکدیگر مجزا نمود و در جدول متد برای هر کدام اطلاعات مجزای ثبت نمود.
در زیر پیاده سازی متد Dispose مربوط به رابط IDisposable و کلاس Test را بوسیله EIMI از یکدیگر مجزا نموده ایم
public class Test : IDisposable { public void Dispose() { Console.WriteLine("Test.Dispose"); } void IDisposable.Dispose() { Console.WriteLine("IDisposable.Dispose"); } }
وقتی که فراخوانی های از این متد ها انجام می دهید، خروجی به صورت زیر برگردانده می شود.
Test obj = new Test(); obj.Dispose(); IDisposable i = obj; i.Dispose(); //output //Test.Dispose //IDisposable.Dispose
در C# ، هنگامی که نام یک رابط به همراه نام متد مربوطه در هنگام پیاده سازی درج می کنید (برای مثال IDisposable.Dispose )، آن متد EIMI نامیده می شود.
در هنگام تعریف EIMI محدودیت های به صورت زیر وجود دارد
- در هنگام پیاده سازی صریح یک تابع نمی توان نحوه دسترسی به آن را تعیین کرد (برای مثال public ویا private)
- همچنین یک متد EIMI نمی تواند با Virtual برچسب بخورد پس توانایی بازنویسی (overide) از این متدها وجود ندارد.
سناریو های مختلفی را می توان برای استفاه از EIMI بیان کرد به عنوان مثال دو رابط زیر را در نظر بگیرید که هر یک دارای متدی با امضاء ها و نوع های برگشتی یکسانی هستند :
//using System.IO; public interface IReader { void SetStream(Stream stream); }
//using System.IO; public interface IReader { void SetStream(Stream stream); }
حالا می خواهیم که هر دو این رابط ها را در یک کلاس پیاده سازی بکنیم، اینکار را چطور انجام می دهید؟ در اینجور سناریو ها EIMI تنها انتخاب است.
//using System.IO; public class TestReader : IReader, IWriter { Stream m_readerStream = null; Stream m_writerStream = null; void IReader.SetStream(Stream stream) { m_readerStream = stream; } void IWriter.SetStream(Stream stream) { m_writerStream = stream; } }
حالا می توان از این متدها براحتی برای رابط های مربوطه استفاده نمود.
IReader reader = new TestReader(); //reader.SetStream(stream) will set m_readerStream IWriter writer = new TestReader(); //writer.SetStream(stream) will set m_writerStream