هل هناك أي أسباب وجيهة لأحدث التغرير في C # محدودة؟

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

  •  13-09-2019
  •  | 
  •  

سؤال

يفشل:

object o = ((1==2) ? 1 : "test");

ينجح:

object o;
if (1 == 2)
{
    o = 1;
}
else
{
    o = "test";
}

الخطأ في العبارة الأولى هو:

لا يمكن تحديد نوع التعبير الشرطي لأنه لا يوجد تحويل ضمني بين "int" و "سلسلة".

لماذا يجب أن تكون هناك أن تكون هناك، وأنا أقسم هذه القيم إلى متغير كائن النوع.

تعديل: المثال أعلاه هو تافهة، نعم، ولكن هناك أمثلة حيث سيكون هذا مفيدا للغاية:

int? subscriptionID; // comes in as a parameter

EntityParameter p1 = new EntityParameter("SubscriptionID", DbType.Int32)
{
    Value = ((subscriptionID == null) ? DBNull.Value : subscriptionID),
}
هل كانت مفيدة؟

المحلول

استعمال:

object o = ((1==2) ? (object)1 : "test");

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

تعديل:في المثال الثاني:

int? subscriptionID; // comes in as a parameter

EntityParameter p1 = new EntityParameter("SubscriptionID", DbType.Int32)
{
    Value = subscriptionID.HasValue ? (object)subscriptionID : DBNull.Value,
}

ملاحظة:
هذا لا يسمى "المشغل التغريري". هو - هي هو مشغل ثلاثي، ولكن يطلق عليه "المشغل الشرطي".

نصائح أخرى

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

أولا، من المرغوب فيه بالنسبة للعديد من التعبيرات إمكانية الحصول على نوع لا لبس فيه يمكن تحديده فقط من محتويات التعبير. هذا أمر مرغوب فيه لعدة أسباب. على سبيل المثال: يجعل بناء محرك IntelliSense أسهل بكثير. أنت تكتب x.M(some-expression. وتحتاج الاحتيال يحتاج إلى أن تكون قادرة على تحليل بعض التعبير, ، حدد نوعه، وتنتج منسرة قبل أن يعلم Intellisense طريقة تشير طريقة XM إلى. لا يمكن أن يعرف IntelliSense ما تشير XM بالتأكيد إذا كان م مثبطا حتى يرى كل الحجج، لكنك لم تكتبها حتى الحجة الأولى حتى الآن.

ثانيا، نحن نفضل كتابة المعلومات للتدفق "من الداخل إلى الخارج"، بسبب السيناريو الدقيق الذي ذكرته للتو: حل الزائد. النظر فيما يلي:

void M(object x) {}
void M(int x) {}
void M(string x) {}
...
M(b ? 1 : "hello");

ماذا يجب أن يفعل هذا؟ يجب أن تسمي الحمل الزائد للكائن؟ يجب أن تسمي أحيانا الحمل الزائد السلسلة وأحيانا استدعاء التحميل الزائد الدولي؟ ماذا لو كان لديك زائد آخر، قل M(IComparable x) - متى تختارها؟

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

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

http://blogs.msdn.com/ericlippert/archive/2007/01/10/lambda-Expressions-vs-anonymous-methods-part-aspx.

قد تقول "حسنا، حسنا، أرى لماذا لا يمكن استخدام الحقيقة التي أقسمها بأمان من قبل المحول البرمجي، وأرى لماذا من الضروري التعبير أن يكون لديك نوع لا لبس فيه، ولكن لماذا لا يكون النوع من كائن التعبير، لأن كلا الطرفين والسلسلة قابلة للتحويل إلى الكائن؟ " هذا يجلب لي إلى وجهة نظري الثالثة:

ثالثا، واحدة من مبادئ التصميم المطبقة الدقيقة ولكن باستمرار من C # هي "لا تنتج أنواعا عن طريق السحر". عند إعطاء قائمة من التعبيرات التي يجب علينا تحديد نوعها، النوع الذي نحدده هو دائما في القائمة في مكان ما. وبعد نحن لسنا مطلقا من نوع جديد واخترها من أجلك؛ النوع الذي تحصل عليه هو دائما واحدة أعطيتنا للاختيار من بينها. إذا قلت للعثور على أفضل نوع في مجموعة من أنواع، نجد أفضل نوع في تلك المجموعة من الأنواع. في المجموعة {int، string}، لا يوجد أفضل نوع عام، والطريقة هناك، "الحيوان، السلاحف، الثدييات، والابي". ينطبق قرار التصميم هذا على المشغل الشرطي، لكتابة سيناريوهات توحيد الاستدلال، لاستنتاج أنواع الصفيف المكتوبة ضمنيا، وهلم جرا.

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

كما يتجنبنا الاضطرار إلى العمل الكثير من القواعد المعقدة حول ما هو أفضل نوع شائع من مجموعة من الأنواع عندما يكون هناك صراعات. لنفترض أن لديك أنواع {foo، bar}، حيث تنفذ كل من الفئتين Iblah، وكلا الفئتين يرثون من باز. ما هو أفضل نوع شائع، إبلا، أن كل من تنفيذ أو باز على حد سواء تمديد؟ نحن لا نريد أن تضطر إلى الإجابة على هذا السؤال؛ نريد تجنبها بالكامل.

أخيرا، أشير إلى أن برنامج التحويل البرمجي C # يحصل بالفعل على تحديد الأنواع خاطئة بشكل كبير في بعض الحالات الغامضة. أول مقاليتي حول هذا هنا:

http://blogs.msdn.com/ericlippert/archive/2006/05/24/TyPe-inenerence-woes-part-one.aspx.

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

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

لماذا تتمثل ميزة X هذه الطريقة في كثير من الأحيان سؤال صعب للغاية للإجابة. من الأسهل بكثير الإجابة على السلوك الفعلي.

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

"Int" هو نوع بدائي، وليس كائنا بينما يعتبر "السلسلة" أكثر من "كائن بدائي". عند القيام بشيء مثل "كائن O = 1"، فأنت فعلا مربع "int" إلى "Int32". إليك رابط لمقال حول الملاكمة:

http://msdn.microsoft.com/en-us/magazine/cc301569.aspx.

بشكل عام، يجب تجنب الملاكمة بسبب تخفيضات الأداء التي يصعب تتبعها.

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

بيان: كائن O = ((1 == 2)؟ 1: "اختبار")؛

مترجم:

  1. ما هي أنواع "1" و "اختبار" في "((1 == 2)؟ 1:" اختبار ")؟ هل تتطابق؟
  2. هل النوع النهائي من # 1 تطابق نوع مشغل الواجب ل "كائن O"؟

نظرا لأن المحول البرمجي لا يقيم # 2 حتى يتم ذلك # 1، فقد فشل.

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