لماذا IEnumerator ترث من IDisposable في حين أن IEnumerator غير عامة لا؟

StackOverflow https://stackoverflow.com/questions/232558

  •  04-07-2019
  •  | 
  •  

سؤال

ولقد لاحظت أن IEnumerator<T> عام يرث من IDisposable، لكن واجهة غير عامة IEnumerator لا. لماذا هو مصمم بهذه الطريقة؟

وعادة، ونحن نستخدم بيان foreach من خلال الذهاب مثيل IEnumerator<T>. الشفرة التي تم إنشاؤها من foreach لديها في الواقع محاولة-أخيرا كتلة يستدعي التخلص () في نهاية المطاف.

هل كانت مفيدة؟

المحلول

وفي الأساس كان خطأ غير مقصود. في C # 1.0، foreach <م> لا دعا Dispose <سوب> 1 . مع C # 1.2 (عرض في VS2003 - ليس هناك 1.1 غريب) بدأت foreach للتحقق في كتلة finally ما إذا كان مكرر تنفيذها IDisposable - كان عليهم أن تفعل ذلك بهذه الطريقة، لأنه جعل بأثر رجعي IEnumerator تمديد IDisposable قد كسر تنفيذ الجميع لل IEnumerator. إذا كان لديهم عمل إلى أنه من المفيد لforeach للتخلص من التكرارات في المقام الأول، وأنا متأكد من أن IEnumerator قمنا بمد IDisposable.

وعندما جاء C # 2.0 و 2.0. NET، مع ذلك، كان لديهم فرصة جديدة - واجهة جديدة والميراث الجديد. يجعل أكثر بكثير من المنطقي أن يكون واجهة تمتد IDisposable بحيث لا تحتاج إلى فحص وقت التنفيذ في كتلة وأخيرا، والآن مترجم يعرف أنه إذا كان مكرر هو IEnumerator<T> يمكن أن تنبعث منها دعوة غير مشروطة لDispose.

وتحرير: انها مفيدة للغاية بالنسبة للDispose ليتم استدعاؤها في نهاية التكرار (ولكن ينتهي). وهو ما يعني أن مكرر يمكن الابقاء على الموارد - مما يجعل من الممكن لذلك، ويقول، قراءة سطر ملف سطرا. كتل مكرر تولد تطبيقات Dispose التي تأكد أن أي كتل finally ذات الصلة "النقطة الحالية التنفيذ" للمكرر يتم تنفيذها عندما يكون التخلص منها - حتى تتمكن من كتابة التعليمات البرمجية العادي داخل مكرر وتنظيف يجب أن يحدث بشكل مناسب


<سوب> 1 في نظرنا إلى الوراء في المواصفات 1.0، تم تحديده بالفعل. أنا لم تتمكن حتى الآن من التحقق من هذا البيان في وقت سابق أن تنفيذ 1.0 لم يدع Dispose.

نصائح أخرى

وIEnumerable لا يرث IDisposable. IEnumerator لا ترث IDisposable ومع ذلك، في حين أن IEnumerator غير عامة لا. حتى عند استخدام <م> foreach لIEnumerable غير النوعية (التي ترجع IEnumerator)، والمترجم لا تزال تولد الاختيار IDisposable والدعوة تخلص () إذا كان العداد بتطبيق واجهة.

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

وأنا أعلم أن هذا هو مناقشة القديمة ولكن أنا reasontly كتب المكتبة حيث كنت IEnumerable من T / T IEnumerator من حيث يمكن للمستخدمين من المكتبة تنفيذ المكررات مخصصة عليهم فقط تنفيذ IEnumerator من T.

ولقد وجدت أنه من الغريب جدا أن IEnumerator من T سوف ترث من IDisposable. علينا أن ننفذ IDisposable إذا كنا نريد لتحرير الموارد unmanged أليس كذلك؟ لذلك سيكون فقط ذات الصلة لالعدادين التي تحمل في الواقع الموارد غير المدارة - مثل تيار IO الخ لماذا لا تسمح للمستخدمين تنفيذ كلا IEnumerator من T وIDisposable على العداد في حال كان من المنطقي؟ في كتابي هذا يخالف مبدأ المسؤولية واحدة - لماذا خلط منطق العداد والأشياء التصرف.

هل ترث IEnumerable` IDisposing؟ وفقا لالعاكس .NET أو MSDN . هل أنت متأكد أنك لا الخلط مع IEnumerator ؟ يستخدم IDisposing لأنه فقط لتعداد مجموعة وليس المقصود لطول العمر.

وقليلا من الصعب أن يكون نهائي في هذا الشأن، إلا إذا كنت تدير للحصول على رد من AndersH نفسه، أو شخص مقرب منه.

ولكن، تخميني هو أنه يتعلق "العائد" الكلمة التي تم تقديمها في C # في نفس الوقت. إذا نظرتم الشفرة التي تم إنشاؤها من قبل المجمع عند استخدام "العائد العائد س"، سترى طريقة اختتم في فئة المساعد التي تطبق IEnumerator. وجود IEnumerator ينزل من IDisposable يضمن أنه يمكن تنظيف عند تعداد كامل.

وIIRC الامر كله عن وجود IEnumerable<T> وIEnumerable هو نتيجة لIEnumerable سبقت الاشياء قالب صافي و. وأظن أن سؤالك في نفس الطريق.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top