لماذا لا يتم تطبيق المعلمات الاختيارية C#4 على الواجهة التي لا يتم فرضها على الفئة التنفيذية؟




.net c#-4.0 (3)

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

public interface MyInterface
{
    void TestMethod(bool flag = false);
}

public class MyClass : MyInterface
{
    public void TestMethod(bool flag)
    {
        Console.WriteLine(flag);
    }
}

وبالتالي:

var obj = new MyClass();        
obj.TestMethod(); // compiler error

var obj2 = new MyClass() as MyInterface;
obj2.TestMethod(); // prints false

لا أحد يعرف لماذا يتم تصميم المعلمات الاختيارية للعمل بهذه الطريقة؟

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

من ناحية أخرى ، يعني هذا الانفصال أنه لا يمكنك دائمًا استخدام فئة الخرسانة والواجهة بشكل متبادل. هذا بالطبع ، لن يكون مشكلة إذا تم تحديد القيمة الافتراضية في التنفيذ ، ولكن إذا كنت تعريض صفك الملموس كواجهة (باستخدام بعض إطار IOC لحقن فئة الخرسانة على سبيل المثال) ، أشر إلى وجود القيمة الافتراضية حيث سيتعين على المتصل تقديمها دائمًا على أي حال.


استكمال: كان هذا السؤال موضوع مدونتي في 12 مايو 2011. شكرا على السؤال الكبير!

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

لنفترض أننا فعلنا ذلك. لنفترض الآن أن المطور لم يكن لديه رمز المصدر للتنفيذ:

// in metadata:
public class B 
{ 
    public void TestMethod(bool b) {}
}
// in source code
interface MyInterface 
{ 
    void TestMethod(bool b = false); 
}
class D : B, MyInterface {}
// Legal because D's base class has a public method 
// that implements the interface method

كيف من المفترض أن المؤلف من D لجعل هذا العمل؟ هل هم مطلوبون في عالمك لاستدعاء مؤلف B على الهاتف ويطلب منهم شحن نسخة جديدة من B التي تجعل هذه الطريقة لها معلمة اختيارية؟

هذا لن يطير. ماذا لو استدعى شخصان مؤلف B ، وأحدهما يريد أن يكون الافتراضي صحيحًا وأن أحدهما يريد أن يكون كاذباً؟ ماذا لو رفض مؤلف B ببساطة اللعب معه؟

ربما في هذه الحالة سيطلب منهم قول:

class D : B, MyInterface 
{
    public new void TestMethod(bool b = false)
    {
        base.TestMethod(b);
    }
}

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


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


يتم وضع علامة على المعلمة الاختيارية بسمة. تخبر هذه السمة المحول البرمجي بإدراج القيمة الافتراضية لهذه المعلمة في موقع الاستدعاء.

المكالمة obj2.TestMethod(); يتم استبدالها بـ obj2.TestMethod(false); عندما يتم تجميع رمز C # إلى IL ، وليس في وقت JIT.

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

من ناحية أخرى ، يعني هذا الانفصال أنه لا يمكنك دائمًا استخدام فئة الخرسانة والواجهة بشكل متبادل.

لا يمكنك فعل ذلك إذا تم تنفيذ طريقة الواجهة بشكل صريح .





optional-parameters