ما هي الفئة التي "تمتلك" موردًا غير مُدار (والتي تنفذ IDisposable)؟

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

سؤال

أنا أعمل على مشروع OSS لجعل شعبية مكتبة معلومات الوسائط أسهل في الاستخدام في .NET، ولكن هذا السؤال قابل للتعميم.

إذا كانت فئة مشتقة د يقوم دائمًا بإنشاء كائن يا عند استدعاء فئتها الأساسية ديسيبلمنشئ.تقوم قاعدة البيانات بتعيين قيمتها على تلك التي يتم إرسالها إلى منشئها، ولكن يتم الإعلان عن القيمة نفسها ديسيبلالطبقة الأساسية ب:

  1. من يملك" يا (AKA mediaInfo في الكود أدناه)؟
  2. في حالة تطبيق .NET، أي من هذه التطبيقات يجب أن يقوم بتطبيق IDisposable؟ملحوظة: يا غير مُدار، أو على الأقل عبارة عن إنشاء مثيل لكائن مُدار ملتف حول مكتبة غير مُدارة، ولكنه يحتاج إلى التنظيف في شكل "MediaInfo.Close();".لست متأكدًا من أن هذا يعتبر "غير مُدار".

للمساعدة في التوضيح، اسمح لي باستخدام الكود الفعلي:

د مشتق من ديسيبل:

// MediaFile is "D" 
public sealed class MediaFile : GeneralStream
{
    public MediaFile(string filePath)
        : base(new MediaInfo(), 0) {
        // mediaInfo is "O"
        mediaInfo.Open(filePath);
    }
}

ديسيبل يحدد ورثته يا, ، مستمدة من ب:

// GeneralStream is "DB"
public abstract class GeneralStream : StreamBaseClass
{
    public GeneralStream(MediaInfo mediaInfo, int id) {
        this.mediaInfo = mediaInfo; // declared in StreamBaseClass
        // ...
    }
}

ب يعلن يا:

// StreamBaseClass is "B"
public abstract class StreamBaseClass
{
    protected MediaInfo mediaInfo; // "O" is declared
    // ...
}
هل كانت مفيدة؟

المحلول

الكائن، الذي يحمل مرجعًا للمورد، يمتلكه.

StreamBaseClass لديه المرجع mediaInfo وينبغي تنفيذها IDisposable.المرجع و Dispose سيتم توريث الطريقة تلقائيًا بواسطة الفئات المشتقة.

نصائح أخرى

إذا كانت الفئة C تمتلك متغيرًا وهو a غير مكشوف المتغير المحلي V الذي ينفذ IDisposable، ثم C يجب أن يكون IDisposable وC's IDisposable يجب أن يتخلص من V.

إذا كانت الفئة D تمتلك موردًا أصليًا N، فيجب أن يكون D معرفًا (مما يؤدي إلى حذف N) و ينبغي أيضا لديك أداة تدمير نهائية تستدعي Dispose() على نفسها لتحرير N.

إذا اتبعت هذا النمط، إذا كان لديك IDisposable، فيجب عليك دائمًا التخلص منه () عند الانتهاء وسيؤدي ذلك إلى حذف كل شيء على طول شجرة الكائنات؛ولكن أيضًا إذا نسيك شخص ما (اقرأ:زميل أو مستخدم لمكتبتك وما إلى ذلك) لن يقوم بتسريب أي كائنات لأنه سيتم تنظيف المورد الأصلي بواسطة أداة الإنهاء D.

مسؤولية أ IDisposable ينتمي إلى الكائن الذي يخلق وذلك ما لم يوجد اتفاق صريح على خلاف ذلك.تُستخدم الاتفاقيات المتعارضة عمومًا في الحالات التي قد لا يكون فيها لدى منشئ المورد أي فكرة عن عمر المستهلك.أود أن أقترح أنه في كثير من الحالات عندما تقوم طريقة المُنشئ أو المصنع بإنتاج ما قد يكون المستهلك الأخير للمارة IDisposable, ، يجب أن تقبل هذه الطريقة معلمة تشير إلى ما إذا كان يجب عليها قبول مسؤولية الاتصال Dispose, ، أو قبول مفوض رد الاتصال الذي سيتم استدعاؤه، إذا لم يكن فارغًا، عندما لا يعود المستهلك بحاجة إلى الكائن.إذا كان منشئ الكائن سيعيش بعد انتهاء عمر المستهلك، فيمكن أن يمر بصفر؛إذا كان المنشئ لن يكون له أي استخدام للكائن بمجرد تسليمه، فيمكنه تمرير الكائن Dispose طريقة.إذا كان المنشئ لا يعرف ما إذا كان سيستمر بعد انتهاء عمر المستهلك، فيمكنه تمرير طريقة تحدد ما إذا كان الكائن لا يزال مطلوبًا أم لا واستدعاءه Dispose ان لم.

فيما يتعلق بحالتك الخاصة، إنشاء IDisposable ضمن استدعاء المنشئ المتسلسل هي وصفة لتسرب الموارد (نظرًا لعدم وجود طريقة لالتفاف استدعاءات المنشئ المتسلسلة في كتلة المحاولة النهائية).إذا كنت ستتعامل مع ذلك بطريقة ما بأمان (على سبيل المثال.باستخدام طريقة المصنع بدلاً من المنشئ المتسلسل، أو باستخدام أ [threadstatic] hack)، أود أن أقترح أنه بما أن منشئ الكائن (الفئة المشتقة) سيعرف عمر المستهلك (الفئة الأساسية)، فإن مسؤولية الملكية والتنظيف يجب أن تظل مع منشئ الكائن.

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