في إصدار حديث من بودكاست DotNet & More Blazor ، NetCore 3.0 Preview ، C # 8 ، ولم نذكر فقط موضوعًا محترقًا مثل C # 8. لم تكن قصة التجربة مع C # 8 كبيرة بما يكفي لتكريس مسألة منفصلة لها ، لذلك تقرر مشاركة وسائل هذا النوع من الرماية.
في هذه المقالة ، أود التحدث عن تجربتي باستخدام C # 8 في الإنتاج لمدة 4 أشهر. يمكنك العثور أدناه على إجابات للأسئلة التالية:
- كيفية "تهجئة" في C # الجديد
- ما هي الميزات كانت مفيدة حقا
- ما بخيبة أمل
يمكن العثور على قائمة كاملة بميزات C # 8 في الوثائق الرسمية لشركة Microsoft . في هذه المقالة ، سأحذف تلك الفرص التي لم أستطع تجربتها لسبب أو لآخر ، وهي:
- أعضاء للقراءة فقط
- أعضاء الواجهة الافتراضية
- هياكل المرجع المتاح
- تيارات غير متزامنة
- المؤشرات والنطاقات
أقترح أن أبدأ بإحدى أكثر الإمكانات اللذيذة ، كما بدا لي من قبل.
تبديل التعبيرات
في أحلامنا ، نقدم هذه الوظيفة وردية للغاية:
int Exec(Operation operation, int x, int y) => operation switch { Operation.Summ => x + y, Operation.Diff => x - y, Operation.Mult => x * y, Operation.Div => x / y, _ => throw new NotSupportedException() };
ولكن لسوء الحظ ، فإن الواقع يجعل التعديلات الخاصة به.
أولاً ، لا توجد إمكانية لدمج الشروط:
string TrafficLights(Signal signal) { switch (signal) { case Signal.Red: case Signal.Yellow: return "stop"; case Signal.Green: return "go"; default: throw new NotSupportedException(); } }
في الممارسة العملية ، هذا يعني أنه في نصف الحالات ، يجب تحويل تعبير التبديل إلى رمز تبديل عادي لتجنب لصق النسخ.
ثانياً ، بناء الجملة الجديد لا يدعم العبارات ، أي رمز لا يُرجع قيمة. يبدو الأمر جيدًا ، وهو ليس ضروريًا ، لكنني فوجئت عندما أدركت عدد المرات التي يتم فيها استخدام التبديل (بالاقتران مع مطابقة الأنماط) لشيء مثل التأكيد في الاختبارات.
ثالثًا ، لا يدعم تعبير التبديل ، الذي يتبع الفقرة الأخيرة ، معالجات الخطوط المتعددة. كيف مخيف نفهم في وقت إضافة السجلات:
int ExecFull(Operation operation, int x, int y) { switch (operation) { case Operation.Summ: logger.LogTrace("{x} + {y}", x, y); return x + y; case Operation.Diff: logger.LogTrace("{x} - {y}", x, y); return x - y; case Operation.Mult: logger.LogTrace("{x} * {y}", x, y); return x * y; case Operation.Div: logger.LogTrace("{x} / {y}", x, y); return x / y; default: throw new NotSupportedException(); } }
لا أريد أن أقول إن التبديل الجديد سيء. لا ، إنه جيد ، ليس جيدًا بدرجة كافية.
أنماط الملكية والموقف
قبل عام ، بدوا لي المرشحين الرئيسيين للحصول على لقب "الفرصة التي غيرت التطور". وكما هو متوقع ، من أجل استخدام القوة الكاملة لأنماط الموضعية والممتلكات ، تحتاج إلى تغيير نهجك في التنمية. وهي ، من الضروري تقليد أنواع البيانات الجبرية.
يبدو ، ما هي المشكلة: خذ واجهة العلامة وتذهب. لسوء الحظ ، هذه الطريقة لها عيب خطير في مشروع كبير: لا أحد يضمن تتبع في وقت التصميم والتوسع في أنواع الجبرية الخاصة بك. لذلك ، من المحتمل جدًا أن تؤدي التغييرات التي تطرأ على الكود بمرور الوقت إلى الكثير من "الإخفاقات الافتراضية" في أكثر الأماكن غير المتوقعة.
أنماط Tuple
لكن "الأخ الأصغر" لإمكانيات المقارنة الجديدة مع العينة أثبت أنه عمل جيد. الشيء هو أن نمط tuple لا يتطلب أي تغييرات في بنية مألوفة من التعليمات البرمجية لدينا ، بل يبسط فقط بعض الحالات:
Player? Play(Gesture left, Gesture right) { switch (left, right) { case (Gesture.Rock, Gesture.Rock): case (Gesture.Paper, Gesture.Paper): case (Gesture.Scissors, Gesture.Scissors): return null; case (Gesture.Rock, Gesture.Scissors): case (Gesture.Scissors, Gesture.Paper): case (Gesture.Paper, Gesture.Rock): return Player.Left; case (Gesture.Paper, Gesture.Scissors): case (Gesture.Rock, Gesture.Paper): case (Gesture.Scissors, Gesture.Rock): return Player.Right; default: throw new NotSupportedException(); } }
ولكن الجزء الأفضل هو أن هذه الميزة ، التي يمكن التنبؤ بها بدرجة كافية ، تعمل بشكل رائع مع طريقة Deconstruct. ما عليك سوى اجتياز فصل دراسي باستخدام "Deconstruct" المطبق للتبديل واستخدام إمكانيات نمط tuple.
باستخدام التصريحات
قد تبدو فرصة بسيطة ، ولكنها تجلب الكثير من البهجة. في جميع الملل ، تتحدث Microsoft عن جانب مثل تقليل التداخل. ولكن دعونا نكون صادقين ، ليس هذا هو ما يهم. ولكن الأمر الخطير حقًا هو الآثار الجانبية لاستبعاد كتلة واحدة من التعليمات البرمجية:
- في كثير من الأحيان ، عند إضافة استخدام ، يتعين علينا سحب الكود "داخل" الكتلة باستخدام طريقة نسخ لصق. الآن نحن لا نفكر في ذلك
- تعد المتغيرات التي تم التصريح بها باستخدامها واستخدامها بعد التخلص من كائن الاستخدام بمثابة صداع حقيقي. مشكلة واحدة أقل
- في الفصول التي تتطلب مكالمات تخلص متكررة ، تكون كل طريقة أطول من سطرين. يبدو تافهًا ، ولكن في حالة وجود العديد من الطرق الصغيرة ، لا يسمح هذا التافه بعرض عدد كافٍ من هذه الطرق على شاشة واحدة
نتيجةً لذلك ، يغير شيئًا بسيطًا مثل استخدام الإعلانات شعور الترميز لدرجة أنك لا ترغب في العودة إلى الإصدار 7.3 من c.
وظائف محلية ثابتة
أن نكون صادقين ، إن لم يكن للمساعدة في تحليل الكود ، لن ألاحظ هذا الاحتمال. ومع ذلك ، فقد استقرت بحزم في الكود الخاص بي: بعد كل شيء ، تعد الوظائف المحلية الثابتة مناسبة تمامًا لدور الوظائف الخالصة الصغيرة ، نظرًا لأنها لا يمكنها دعم إغلاق متغيرات الطريقة. نتيجةً لذلك ، الأمر أسهل في القلب ، لأنك تفهم أن هناك خطأً واحداً أقل احتمالًا في الكود.
أنواع مرجعية لاغية
وبالنسبة للحلوى ، أود أن أذكر أهم ميزة في C # 8. في الحقيقة ، تحليل أنواع المراجع الفارغة يستحق مقالة منفصلة. أريد فقط أن أصف الأحاسيس.
ملخص
بالطبع ، لا تصل الفرص المتاحة إلى ثورة كاملة ، ولكن هناك فجوة أقل وأقل بين C # و F # / Scala. سواء أكان ذلك جيدًا أم سيئًا ، فسيخبرنا الوقت.
في وقت إصدار هذا المقال ، ربما تكون C # 8 قد استقرت بالفعل في مشروعك ، لذلك أتساءل ، ما هي مشاعرك تجاه الإصدار الجديد من لغتنا المفضلة؟