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

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

Span وMemory وأعمار الاستعارة

استخدم مناظر ذاكرة متجاورة مع حفظ العمر والتعديل وملكية التخزين الأساسي.

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

أهداف الدرس

  • شرح Span كمنظور مستعار لا مالك.
  • احترام قيود هروب ref struct والتعليق.
  • اختيار Memory وبروتوكول المالك للحدود غير المتزامنة.

تصف Span تخزينا لا تملكه

تمثل Span<T> كـref struct منطقة متجاورة وقد تنظر لمصفوفة أوالمكدس أوذاكرة أصلية مناسبة. لا تملك الهدف ولا تمدد استعارته. ينشئ التقسيم منظورا لا نسخة، وتقيد ReadOnlySpan الكتابة عبرها لا عبر اسم آخر. يمكن أن يبقى عنصر قابل للتعديل مشتركا حتى لو كان الوصول الحالي للقراءة فقط؛ الثبات وعد من المالك لا اسم المنظور.

تحتاج العمليات حدودا وهدفا حيا. تستفيد المصفوفة من تتبع المدار بينما تحتاج المجّمعة والأصلية عقد استعارة وتحرير. لا تخف الصياغة سؤال من يعيد استخدام البايتات ومتى. عند التخزين المجمع لا تعني صلاحية مرجع مدار أن استعارة محتواه ما زالت سارية بعد إعادته للمجمع.

ملاحظة مشاركة المنظور مباشرة

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

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

csharp تشارك شريحة Span عناصر المصفوفة
using System;

int[] values = { 1, 2, 3, 4 };
Span<int> middle = values.AsSpan(1, 2);
middle[0] = 9;
Console.WriteLine(string.Join(",", values));
Console.WriteLine($"length={middle.Length}");
الناتج المتوقع
1,9,3,4
length=2

تبدأ عند فهرس واحد فتستبدل أول كتابة الاثنين بتسعة.

لا يهرب تخزين المكدس من عمره

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

تمنع قواعد ref هروبات كثيرة كإعادة Span محلية من المكدس. أبق المقتطف غير الصالح غير قابل للتشغيل. يتجاوز unsafe الحماية ويتطلب برهانا مستقلا؛ لا تحتاجه أمثلتنا. تثبت أخطاء ref-safety أن اقتراح الواجهة لا يحفظ العمر، ويجب إعادة التصميم بدلا من الالتفاف على الفحص دون حاجة.

csharp منظور مكدس صغير مهيأ وتزامني
using System;

ReadOnlySpan<int> values = stackalloc int[] { 1, 2, 3 };
int total = 0;
foreach (int value in values) total += value;
Console.WriteLine($"sum={total}");
الناتج المتوقع
sum=6

تستهلك العناصر المهيأة قبل نهاية النطاق فتنتج ستة.

قواعد التعليق مرتبطة بإصدار اللغة

قول إن ref struct ممنوعة دائما في async قديم وواسع. خففت C#13 بعض القيود مع منع الاستخدام عبر await وفق الكتل وسلامة ref، وتغيرت قيود المجتاز أيضا. يتبع أساس C#14 التحليل الحالي لا العبارة القديمة. تغيرت قواعد السماح بالمحليات في C#13، لكن عدم عبور التخزين المقيد للتعليق يظل التزاما يجب فحصه.

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

ينشئ التجميع استعارة لا ملكية دائمة

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

تكشف MemoryPool وIMemoryOwner مالكا ولا تلغي القواعد. اختبر الفراغ والحد والنسخ المتداخل وفق الواجهة والإلغاء والاكتمال قبل الإعادة. قس الوفر والاحتفاظ معا؛ فقد يحتفظ المجمع ويعقد الملكية. تضيف إعادة الاستخدام وفرا محتمل الكلفة، لكنها تضيف أيضا مسؤولية عدم بقاء مستعير أو بيانات حساسة عند الإعادة.

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

تبدو Span للقراءة متغيرة.

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

يرفض المترجم هروب Span.

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

تقرأ عملية مخزنا أعيد استخدامه.

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

اختبر فهمك

1. هل تضمن ReadOnlyMemory<byte> ثبات البايتات للمستهلك غير المتزامن؟

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

لا؛ تقيد المسار وقد يعدل المالك أويرد الأصل. يضمن العقد ملكية مستقرة أواستعارة حصرية طوال العملية أونسخة. يحل التخزين على الكومة قيد تمثيل لا مزامنة وصلاحية استعارة.

2. طلبت Rent مئة وأعادت128. أي طول يعالج البروتوكول؟

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

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

أهم ما تعلمته

  • لا يملك المنظور أصله ولا يجمده ولا يمدد استعارته.
  • احترم قواعد ref الحالية وحدد الإصدار.
  • يتطلب التجميع والاستعارة غير المتزامنة اكتمالا قبل الاستخدام مجددا.

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