[C#] بما أن .NET لها جامع قمامة لماذا نحتاج إلى finalizers / destructors / dispose-pattern؟



Answers

الإجابات السابقة جيدة ، لكن دعوني أؤكد على النقطة المهمة هنا مرة أخرى. على وجه الخصوص ، قلت ذلك

إذا فهمت بشكل صحيح سوف تنظيف وقت تشغيل .net دائما بعد لي.

هذا صحيح جزئيا فقط. في الواقع ، تقدم .NET الإدارة التلقائية لمورد معين فقط : الذاكرة الرئيسية. جميع الموارد الأخرى تحتاج إلى تنظيف يدوي. 1)

ومن الغريب أن الذاكرة الرئيسية تحصل على وضع خاص في كل المناقشات تقريباً حول موارد البرنامج. هناك بالطبع سبب وجيه لهذا - الذاكرة الرئيسية هي في كثير من الأحيان الموارد الأكثر ندرة. ولكن تجدر الإشارة إلى وجود أنواع أخرى من الموارد أيضًا ، والتي تحتاج أيضًا إلى الإدارة.

1) يتمثل المحاولة المعتادة في مزج عمر الموارد الأخرى في العمر الافتراضي لمواقع الذاكرة أو المعرّفات في الشفرة - ومن هنا كان وجود المخططات النهائية.

Question

إذا فهمت بشكل صحيح سوف تنظيف وقت تشغيل .net دائما بعد لي. لذلك إذا قمت بإنشاء كائنات جديدة وأوقفت الرجوع إليها في التعليمة البرمجية الخاصة بي ، فسوف يقوم وقت التشغيل بتنظيف هذه الكائنات وتحرير الذاكرة التي يشغلونها.

وبما أن هذه هي الحالة فلماذا تحتاج بعض الكائنات أن يكون لها طريقة تدمير أو التخلص؟ لن تنظيف وقت التشغيل بعدهم عندما لا يشار إليها بعد الآن؟




قد تحتاج بعض الكائنات إلى تنظيف عناصر منخفضة المستوى. مثل الأجهزة التي تحتاج إلى إغلاق ، إلخ.




يعرف أداة تجميع مجمعي البيانات المهملة .NET كيفية معالجة الكائنات التي تتم إدارتها في وقت تشغيل .NET. ولكن يتم استخدام نمط Dispose (IDisposable) بشكل أساسي للكائنات غير المدارة التي يستخدمها التطبيق.

بمعنى آخر ، لا يعرف وقت تشغيل .NET بالضرورة كيفية التعامل مع كل نوع من الأجهزة أو التعامل معه (إغلاق اتصالات الشبكة ، مقابض الملفات ، أجهزة الرسومات ، إلخ) ، لذلك فإن استخدام أداة IDisposable يوفر طريقة لقول "دعني تنفيذ بعض تنظيف بلدي "في نوع. رؤية ذلك التنفيذ ، يمكن لـ جامع البيانات المهملة استدعاء Dispose () والتأكد من أن يتم تنظيف الأشياء خارج الكومة المدارة.




هناك عدد قليل (قليل جدًا) من الحالات التي قد يكون من الضروري فيها القيام بإجراء محدد عند عدم استخدام كائن مُدار نقيًا ، لا يمكنني الحصول على مثال من قمة رأسي ، ولكني رأيت زوجين الاستخدامات المشروعة على مر السنين. ولكن السبب الرئيسي هو تنظيف أي موارد غير مدارة قد يستخدمها الكائن.

لذلك ، بشكل عام ، لن تحتاج إلى استخدام نمط التخلص / إنهاء الصور إلا إذا كنت تستخدم موارد غير مُدارة.




  1. هناك أشياء لا يستطيع جامع القمامة تنظيفها بعدك
  2. حتى مع الأشياء التي يمكن تنظيفها ، يمكنك مساعدتها في التنظيف في وقت أقرب



التفسير التبسيطي:

  • تم تصميم التخلص للتخلص من الموارد غير الذاكرة ، وبالتحديد الموارد النادرة . على سبيل المثال ، مقبض النافذة أو اتصال قاعدة البيانات.
  • تم تصميم Finalization للتخلص غير الحتمية لموارد غير الذاكرة ، عادةً كخلفية في حالة عدم استدعاء Dispose.

بعض المبادئ التوجيهية لتنفيذ طريقة Finalize:

  • تنفيذ فقط وضع اللمسات الأخيرة على الكائنات التي تتطلب وضع اللمسات الأخيرة ، لأن هناك تكلفة أداء مقترنة بطرق وضع الصيغة النهائية.
  • إذا كنت تحتاج إلى طريقة Finalize ، ففكر في تطبيق IDisposable للسماح لمستخدمي النوع الخاص بك بتجنب تكلفة استدعاء طريقة Finalize.
  • يجب حماية أساليب اللمسة النهائية بدلاً من العامة.
  • يجب أن تقوم طريقة Finalize الخاصة بك بتحرير أي موارد خارجية يمتلكها النوع ، ولكن فقط تلك التي تمتلكها. لا ينبغي أن تشير إلى أي موارد أخرى.
  • لا تقدم CLR أي ضمانات فيما يتعلق بالترتيب الذي يتم فيه استدعاء طرق Finalize. كما يلاحظ دانيال في تعليقه ، فإن هذا يعني أن طريقة Finalize لا ينبغي أن تصل إلى أي أنواع مرجعية من الأعضاء إن أمكن ، لأن هذه قد يكون لها (أو قد يكون لها يومًا ما) موادها النهائية الخاصة.
  • عدم استدعاء طريقة Finalize مباشرة على أي نوع آخر غير النوع الأساسي للنوع.
  • حاول تجنب أي استثناء غير معالج في طريقة Finalize الخاصة بك ، لأن ذلك سينهي العملية (في 2.0 أو أعلى).
  • تجنب القيام بأي مهمة طويلة الأمد في طريقة Finalizer الخاصة بك ، حيث يؤدي ذلك إلى حظر مؤشر ترابط Finalizer ومنع تنفيذ أساليب Finalizer الأخرى.

بعض المبادئ التوجيهية لتنفيذ طريقة التخلص:

  • قم بتطبيق نمط التصميم التصرف على النوع الذي يقوم بتغليف الموارد التي تحتاج صراحة لتحريرها.
  • قم بتطبيق نمط التصميم التصرف على نوع أساسي يحتوي على واحد أو أكثر من الأنواع المشتقة التي تحتفظ بالموارد ، حتى إذا لم يكن النوع الأساسي.
  • بعد استدعاء Dispose على مثيل ، منع تشغيل الأسلوب Finalize من خلال استدعاء الأسلوب GC.SuppressFinalize. الاستثناء الوحيد لهذه القاعدة هو الوضع النادر الذي يجب أن يتم فيه العمل في وضع اللمسات الأخيرة غير المشمولة بالتخفيض.
  • لا تفترض أنه سيتم استدعاء التخلص. يجب أيضًا نشر الموارد غير المدارة التي يمتلكها النوع في طريقة Finalize في حالة عدم استدعاء Dispose.
  • قم بإلقاء ObjectDisposedException من طرائق المثال في هذا النوع (عدا Dispose) عندما يتم التخلص من الموارد بالفعل. لا تسري هذه القاعدة على طريقة التخلص لأنها يجب أن تكون قابلة للاستدعاء عدة مرات دون إلقاء استثناء.
  • نشر دعوات للتخلص من خلال التسلسل الهرمي للأنواع الأساسية. يجب أن تقوم طريقة التصرف بتحرير جميع الموارد المحتفظ بها بواسطة هذا الكائن وأي كائن يمتلكه هذا الكائن.
  • يجب أن تفكر في عدم السماح باستخدام كائن ما بعد استدعاء طريقة التخلص منه. إعادة تكوين كائن تم التخلص منه بالفعل هو نمط صعب للتنفيذ.
  • السماح باستدعاء أسلوب Dispose أكثر من مرة دون طرح استثناء. يجب ألا تفعل الطريقة أي شيء بعد المكالمة الأولى.



Links