VB.NET-هل يجب إضافة طريقة الإنهاء عند تنفيذ IDisposable؟
-
02-07-2019 - |
سؤال
في Visual Studio، عندما أكتب السطر "Implements IDisposable
"، يضيف IDE تلقائيًا:
- أ
disposedValue
متغير العضو - أ
Sub Dispose() Implements IDisposable.Dispose
- أ
Sub Dispose(ByVal disposing As Boolean)
ال Dispose()
يجب تركه بمفرده، ويجب إدخال رمز التنظيف Dispose(disposing)
.
ومع ذلك التخلص من النمط النهائي يقول يجب عليك تجاوز أيضا Sub Finalize()
للإتصال Dispose(False)
.لماذا لا يضيف IDE هذا أيضًا؟هل يجب أن أضيفه بنفسي أم أنه يسمى ضمنيًا بطريقة ما؟
يحرر: هل لديك أي فكرة عن سبب قيام IDE بإضافة 80% من العناصر المطلوبة تلقائيًا ولكنه يترك طريقة الإنهاء؟أليس المغزى من هذا النوع من الميزات هو مساعدتك لا ننسى هذه الأشياء؟
تحرير 2: شكرًا لكم جميعًا على إجاباتكم الممتازة، وهذا أصبح الآن منطقيًا تمامًا!
المحلول
إذا كنت تمتلك بالفعل موارد غير مُدارة والتي لن يتم تنظيفها تلقائيًا بواسطة أداة تجميع البيانات المهملة وتنظيفها في Dispose()، فنعم، يجب عليك أن تفعل الشيء نفسه في Finalize().
إذا كنت تقوم بتنفيذ IDisposable لسبب آخر، فلن يكون تنفيذ Finalize() مطلوبًا.
السؤال الأساسي هو هذا:إذا لم يتم استدعاء Dispose() وتم جمع البيانات المهملة لكائنك، فهل ستتسرب الذاكرة؟إذا كانت الإجابة بنعم، قم بتنفيذ Finalize.إذا كان الجواب لا، لا تحتاج إلى ذلك.وتجنب أيضًا تنفيذ Finalize "لمجرد أنه أكثر أمانًا".من المحتمل أن تحتاج الكائنات ذات أدوات الإنهاء المخصصة إلى مرورين من GC لتحريرها - مرة واحدة لوضعها في قائمة انتظار أدوات الإنهاء المعلقة، وتمريرة ثانية لتحرير ذاكرتها فعليًا.
نصائح أخرى
لا، لا تحتاج إلى الإنهاء إلا إذا كانت لديك موارد غير مُدارة للتنظيف.
في معظم الحالات، يكون السبب وراء إمكانية التخلص من الفئة هو أنها تحتفظ بمراجع إلى كائنات IDisposable مُدارة أخرى.في هذه الحالة، لا توجد طريقة نهائية ضرورية أو مرغوبة.
Implements IDisposable
Public Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Protected Overloads Sub Dispose(ByVal disposing As Boolean)
If disposing Then
' Free other state (managed objects).
End If
' Free your own state (unmanaged objects).
' Set large fields to null.
End Sub
Protected Overrides Sub Finalize()
Dispose(False)
MyBase.Finalize()
End Sub
كما قال الآخرون، لا تحتاج إلى تنفيذ أداة الإنهاء إلا إذا كنت تحتفظ مباشرةً بموارد غير مُدارة.أيضًا، بافتراض أنك تعمل في .NET 2.0 أو إصدار أحدث، فمن غير المحتمل أن تحتاج إلى تنفيذ أداة نهائية لأنه يمكن استخدام SafeHandle عادةً لتغليف مواردك غير المُدارة.
كتبت أ مشاركة مدونة طويلة إلى حد ما تغطية الخلفية وتنفيذ IDisposable و Finalizers منذ فترة، والتي قد تستحق القراءة إذا لم تكن واضحًا تمامًا بشأنها.