سؤال

public class Foo : IFooBarable {...}
public class Bar : IFooBarable {...}

فلماذا لن يتجمع هذا ...

int a = 1;
IFooBarable ting = a == 1 ? new Foo() : new Bar();

لكن هذا سوف ...

IFooBarable ting = a == 1 ? new Foo() : new Foo();
IFooBarable ting = a == 1 ? new Bar() : new Bar();
هل كانت مفيدة؟

المحلول

يحاول المترجم أولاً تقييم التعبير الأيمن:

? new Foo() : new Bar();

لا يوجد تحويل ضمني بين هذين رسالة الخطأ. يمكنك ان تفعلها:

IFooBarable ting = a == 1 ? (IFooBarable)(new Foo()) : (IFooBarable)(new Bar());

نصائح أخرى

هذا مغطى في القسم 7.13 من مواصفات لغة C#. في الأساس ما يقتل هذا السيناريو هو أنه يجب أن يكون هناك تحويل ضمني بين أنواع القيم 2 للمعاملات الثلاثية. يعتبر هذا التحويل في ارتياح نوع المتغير.

ذلك إما Foo يجب أن تكون قابلة للتحويل إلى Bar أو العكس. لا يحدث خطأ في التجميع.

يعمل هذا الأخير 2 لأنهم يعتبرون نوعًا واحدًا فقط (أيضًا Foo أو Bar). لأنها من نفس النوع الذي يحدد نوع التعبير بسيط ويعمل بشكل جيد.

فقط لإضافة بعض الشيء إلى الإجابات الصحيحة المنشورة هنا: هناك إرشادات للتصميم تؤدي إلى هذه المواصفات.

الأول هو أننا نسبب من "من الداخل إلى الخارج". عندما تقول

double x = 2 + y;

نعمل أولاً على نوع x ، ثم نوع 2 ، ثم نوع y ، ثم نوع (2+y) ، وأخيراً ، نعمل على ما إذا كان X و (2+y) لهما أنواع متوافقة. لكننا لا نستخدم نوع x في تحديد نوع 2 أو y أو 2+y.

السبب في أن هذه قاعدة جيدة هو أن نوع "المتلقي" هو بالضبط ما نحاول العمل عليه:

void M(Foo f) {}
void M(Bar b) {}
...
M(x ? y : z);

ماذا نفعل هنا؟ علينا أن نحدد نوع التعبير الشرطي من أجل القيام بدقة التحميل الزائد ، من أجل تحديد ما إذا كان هذا سيذهب إلى Foo أو Bar. لذلك ، لا يمكننا استعمال حقيقة أن هذا ، على سبيل المثال ، الذهاب إلى Foo في تحليلنا لنوع التعبير الشرطي! هذه مشكلة دجاج وبيغ.

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

العنصر الثاني هو أننا لا "سحر" لنوع لك. عندما يتم إعطاء مجموعة من الأشياء التي يجب أن نستنتج منها نوعًا ما ، فإننا نستنتج دائمًا نوعًا كان بالفعل أمامنا.

في مثالك ، يذهب التحليل مثل هذا:

  • العمل على نوع النتيجة
  • العمل على نوع البديل
  • ابحث عن أفضل نوع متوافق مع كل من النتيجة والبديل
  • تأكد من وجود تحويل من نوع التعبير الشرطي إلى نوع الشيء الذي يستخدم التعبير الشرطي.

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

b ? new Cat() : new Dog()

نقول "نوع التعبير الشرطي هو أفضل نوع في المجموعة {cat ، dog}". لا نقول "نوع التعبير الشرطي هو أفضل نوع متوافق مع كل من القط والكلب". سيكون ذلك الثدييات ، لكننا لا نفعل ذلك. بدلاً من ذلك ، نقول "النتيجة يجب أن تكون شيئًا رأيناه بالفعل" ، ومن هذين الخيارين ، ليس الفائز الواضح. ان كان هذا ما تقول

b ? (Animal) (new Cat()) : new Dog()

ثم لدينا خيار بين الحيوانات والكلب ، والحيوان هو الفائز الواضح.

الآن ، لاحظ أننا في الواقع لا ننفذ بشكل صحيح المواصفات C# عند إجراء تحليل هذا النوع! للحصول على تفاصيل الخطأ ، انظر مقالة - سلعة عليه.

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

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