محتويات الدورة

C# / المتقدم: الأعمار والتزامن وتصميم التنفيذ / الدرس 13

دلالات القيم والمراجع وجمع القمامة

حلل النسخ وإمكان الوصول بدل شعارات المكدس والكومة وافصل استعادة الذاكرة من تحرير المورد.

وقت القراءة التقريبي: 4 دقيقةتاريخ مراجعة المحتوى
في هذه الصفحة

أهداف الدرس

  • تتبع قيم struct ومراجع class عند الإسناد.
  • شرح boxing والنسخ السطحي الحامل للمراجع.
  • تحديد الاحتفاظ الممكن الوصول ومسؤوليات التخلص المحدد.

دلالات النسخ أهم من تخمين الموضع

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

اختر struct لدلالته لا لتجنب كومة مفترضة فقط. تغير النسخ الكبيرة والتعديل وboxing والتضمين الكلفة. تمثل class الهوية والمشاركة عمدا؛ وثق تعديل المرئي أوالنسخة المحلية. يجب أن يشرح الاختيار هل للبيانات هوية مشتركة أم قيمة تستبدل كاملة، ثم تقاس كلفة هذا الاختيار.

مقارنة القيم المستقلة والكائنات المشتركة

ينسخ المثال struct متغيرة ومرجع class. يبقى حقل الأصل واحدا بعد تعديل نسخة القيمة، ويتغير الكائن المشترك لتسعة عبر الاسم الآخر. يبرر الإسناد الخرج دون عناوين أوجمع قسري. يختلف تعديل حقل في النسخة عن تعديل كائن تشير إليه النسختان؛ يفصل رسم الكائنات بين الحالتين.

تنسخ struct الحاملة لـList مرجعها فتشترك العناصر. تقيد readonly struct حقولها ولا تجمد الأهداف. تجنب القيم المتغيرة العامة حين يعدل المستدعي مؤقتا أويخطئ الهوية. تجعل القيم المتغيرة المعروضة عبر خصائص أو واجهات النسخ المؤقتة أسهل في إساءة الفهم، فيستحق تصميمها الحذر.

csharp نسخ القيمة مقابل مشاركة المرجع
using System;

var value = new ValuePoint { X = 1 };
var copiedValue = value;
copiedValue.X = 9;
var reference = new ReferencePoint { X = 1 };
var alias = reference;
alias.X = 9;
Console.WriteLine($"value={value.X} copied={copiedValue.X} reference={reference.X}");

internal struct ValuePoint { public int X; }
internal sealed class ReferencePoint { public int X; }
الناتج المتوقع
value=1 copied=9 reference=9

للبنية حقلا X مستقلان ويحدد متغيرا الصنف حقلا واحدا.

ينشئ boxing نسخة قيمة منفصلة

ينشئ boxing لقيمة غير خالية داخل object نسخة منها. لا يغير الأصل لاحقا النسخة، ويتطلب unboxing النوع المتوافق لا تحويلا عدديا عاما. تتجنب المجموعات العامة صناديق عديدة لكن الواجهة مهمة. يتطلب فك الصندوق النوع الذي وضع فيه فعلا؛ لا تحول محاولة فك int معلب إلى long تحويلا عدديا عاديا.

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

csharp تحفظ البنية المعلبة قيمتها المنسوخة
using System;

var point = new Point { X = 1 };
object boxed = point;
point.X = 9;
Console.WriteLine($"original={point.X} boxed={((Point)boxed).X}");

internal struct Point { public int X; }
الناتج المتوقع
original=9 boxed=1

يبقي تغيير point بعد التعليب النسخة عند واحد.

تبقى البيانات القابلة للوصول مسؤولية البرنامج

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

لا تعد بإعادة فورية بعد null أوClear أوGC.Collect. يختلف الجمع وإعادة الاستخدام وإعادة النظام. الأجيال وكومة الكبير تفاصيل تنفيذ تتحقق من وثائق النسخة الفعلية. يجب أن تقاس مسارات الاحتفاظ الحقيقية قبل افتراض أن تقليل تخصيص جديد يصلح نمو الذاكرة الحية.

لا يملك الجامع موعد كل مورد خارجي

قد يملك مغلف غير قابل للوصول مقبضا محدودا حتى تنظيفه. تعبر Dispose وawait using عن عمر محدد، والإنهاء النهائي احتياط لا تحرير سريع معتاد. تساعد SafeHandle ملكية المقابض الأصلية. تفيد SafeHandle عند تغليف مورد أصلي لأن التحرير يحتاج سلامة أمام الاستثناءات دون نشر مؤشرات خام في التطبيق.

قس الاحتفاظ بحمل ممثل. لا يثبت Count صغير صغر الأهداف. اختبر إلغاء الاشتراك والاكتمال والتخلص دون موعد finalizer غير الحتمي. أصلح الوصول والملكية قبل إجبار الجمع. لا تجعل الاختبارات تنتظر finalizer بمدة تخمينية؛ افحص عقد الإغلاق وإلغاء الاشتراك والاكتمال المحدد بدلا منه.

الأخطاء الشائعة وإصلاحها

تشارك نسخة struct قائمة دون توقع.

لماذا يحدث؟
نُسخ المرجع لا هدفه عميقا.
كيف تصلحه؟
انسخ الداخل أووثق المشاركة.
كيف تتجنب تكراره؟
راجع كل حقل مرجعي.

لا تعكس القيمة المعلبة التحديث.

لماذا يحدث؟
التقط boxing نسخة.
كيف تصلحه؟
استخدم المرجع أوالاستبدال المقصود.
كيف تتجنب تكراره؟
اختبر حدود التعليب للقيم المتغيرة.

لا يصغر الجمع مخبأ ناميا.

لماذا يحدث؟
ما زالت الكائنات قابلة للوصول.
كيف تصلحه؟
حد العناصر أوحررها بسياسة عمر.
كيف تتجنب تكراره؟
حلل مسارات الاحتفاظ لا التخصيص فقط.

اختبر فهمك

1. لماذا قدتكشف readonly struct قاموسا متغيرا؟

اعرض الحل المشروح

تقيد readonly حقول البنية لكن حقل القاموس مرجع ويعدل آخر هدفه ما لم تمنع الملكية. استخدم تمثيلا ثابتا أونسخا خاصة بعرض واضح؛ لا تساو readonly والثبات المتكرر.

2. ناشر طويل العمر يشير لمشترك بحدث. ما سؤال العمر قبل لوم الجامع؟

اعرض الحل المشروح

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

أهم ما تعلمته

  • النسخ ومشاركة المراجع قواعد دلالة لا شعارات موضع.
  • للتعليب والنسخ السطحي هويات مختلفة.
  • حد الوصول وتخلص من الموارد ولا تجعل الجمع بروتوكول ملكية.

المراجع الرسمية