PDA

View Full Version : چگونه از IDisposable استفاد کنیم



Wily_Fox
شنبه 09 شهریور 1392, 12:55 عصر
با سلام و خسته نباشید

دوستان عزیز اگه امکانش هست منو راهنمایی کنید:

1- آیا همه کلاس هایی که تعریف می کنیم نیاز به مشتق گرفتن از IDisposable دارند؟

2- چه زمانی یک کلاس نیاز به مشتق گرفتن از IDisposable دارد؟

3- چگونه متد Dispose رو پیاده سازی کنیم؟

متشکرم

khokhan
شنبه 09 شهریور 1392, 13:35 عصر
با سلام و خسته نباشید

دوستان عزیز اگه امکانش هست منو راهنمایی کنید:

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

FastCode
شنبه 09 شهریور 1392, 14:15 عصر
جواب سوال سوم عالی بود(البته دقیقا جواب این سوال نبود).ولی با این حال چند وقت بود کسی این مقدار راجع به اینترفیس ها توضیح نداده بود.یاد قدیم افتادم.
جواب سوال اول منفیه.
۲.
شما فقط زمانی نیاز به implement کردن IDisposable دارید که کلاس شما مستقیما به منابع سیستم دسترسی داشته باشد یا مرجعی به کلاسی داشته باشد که مستقیما به منابع سیستم دسترسی داشته باشد و آزاد کردن منابع آن حیاتی باشد.خب این یعنی چی؟
اول socket رو مثال میزنم.socket به منابع سیستم دسترسی دارد.و تا زمانی که Dispose نشود نمیتواند به سیستم عامل دستور بدهد که socket را ببندد.
Stream رو مثال میزنم.Stream یک مقدار پیچیده تره.چون میتونه مستقیم به منابع سیستم وصل باشه یا از یک Stream دیگه استفاده کنه.به هر حال وقتی Dispose میشه اگر Base داشته باشه متود Dispose رو صدا میزنه.در غیر این صورت خودش به منابع دسترسی داره که در خیلی از مواقع باید بسته بشن(مثل فایل ها;FileStream). یا در خیلی از مواقع لازم نیست که بسته بشن(مثل MemoryStream).
http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx

برای اینکه بیشتر با موضوع آشنا بشید پیشنهاد میکنم راجع به GC و مخصوصا Finalizer ها مطالعه کنید:
http://stackoverflow.com/questions/2344240/what-is-relation-between-gc-finalize-and-dispose
http://stackoverflow.com/questions/13954829/gc-collect-and-finalize

این رو هم جست و جو کن:(Google Image)
.net Stream class hierarchy

مهرداد صفا
یک شنبه 10 شهریور 1392, 12:02 عصر
با سلام.
این تاپیکها را مطالعه بفرمایید:
http://barnamenevis.org/showthread.php?352534

http://barnamenevis.org/showthread.php?250544-%D9%81%D8%B1%D9%82-%D8%A8%D9%84%D8%A7%DA%A9-using-%D8%A8%D8%A7-%D8%A8%D9%84%D8%A7%DA%A9%D9%87%D8%A7%DB%8C-%D8%A7%DB%8C%D9%88%D9%86%D8%AA%D9%87%D8%A7&highlight=gc%3Bdispose%3B

http://barnamenevis.org/showthread.php?351809-%D8%A2%DB%8C%D8%A7-%D8%A7%D8%B4%DB%8C%D8%A7%D8%A1-%D8%A8%D8%B9%D8%AF-%D8%A7%D8%B2-%D8%A7%DB%8C%D8%AC%D8%A7%D8%AF-%D9%86%D8%A8%D8%A7%DB%8C%D8%AF-%D8%AA%D8%AE%D8%B1%DB%8C%D8%A8-%D8%B4%D9%88%D9%86%D8%AF-%DB%8C%D8%A7-%D8%A7%DB%8C%D9%86%DA%A9%D9%87%D8%9F&highlight=gc%3Bdispose%3B

http://barnamenevis.org/showthread.php?351399-%D8%A2%D8%B2%D8%A7%D8%AF-%D8%B3%D8%A7%D8%B2%DB%8C-%D9%81%D8%B6%D8%A7%DB%8C-%D8%AD%D8%A7%D9%81%D8%B8%D9%87-%DB%8C-Ram&highlight=gc%3Bdispose%3B

http://barnamenevis.org/showthread.php?83503-%D8%AA%D8%A7%D8%A8%D8%B9-%D9%85%D8%AE%D8%B1%D8%A8-%DB%8C%DA%A9-%DA%A9%D9%84%D8%A7%D8%B3&highlight=gc%3Bdispose%3B