سؤال

هناك عدد قليل من الوظائف بالفعل على تجاوز تكدس حول هذا النوع من الأشياء ولكن ليس بالضبط نفس الشيء - لذلك الاعتذار مقدما إذا كان هذا شيء تم الرد عليه بالفعل.

لماذا هذا لا يعمل:

public class MyBase { }

public class MyUtils
{
    public bool Foo<T> (T myObject) { return true; }
    public bool Foo (MyBase myBaseObject) { return false; }

    public void Go<T> (IEnumerable<T> items)
    {
        foreach (var item in items)
        {
            // this test fails
            Assert.IsFalse (Foo (item));
        }
    }
}

إذا قمت باستدعاء GO () أعلاه وتمرير في حمولة من كائنات MyBase، سيتصل كل مكالمة إلى FOO FOO () عام ()، والتي تعود TRUE.

new MyUtils ().Go (new MyBase[] { new MyBase (), new MyBase () });      

لماذا لا يتصل بإصدار MyBase المتخصص بدلا من ذلك؟ إذا قمت باستدعاء FOO (MyBase New Mybase ()) مباشرة، فهذا ينتشر بشكل صحيح الذي يدعو إلى صنعه. هل هذا بسبب نقص التباين للمجموعات في C # 3، أو أنا مجرد سخيفة وعدم القيام بذلك بشكل صحيح؟

شكرا!

إسحاق

هل كانت مفيدة؟

المحلول

لا يطلق على "المتخصصة" لأن مترجم يخطف الطريقة التي تتصل بها عند البرنامج (الذي في هذه الحالة، هو Go وظيفة) هي تجميع وانتاج, ليس عندما يركض.

عندما يكون المحول البرمجي تجميع Go وظيفة، والمعلومات الوحيدة التي لديها هي أن هناك بعض الشيء من النوع T. وبعد ليس لديه أي فكرة قد تكون في وقت لاحق من وقت تزويدها بتوفير كائن من النوع MyBase. وبعد الخيار الوحيد الذي لديه هو اختيار Foo<T> الزائد، وهكذا فإنها تخبز في البرنامج المترجم.

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

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

 public void Go<T> (IEnumerable<dynamic> items)

ثم سيستخدم الإرسال الديناميكي في وقت التشغيل لاختيار ما يسمى الحمولة الزائدة، وسوف استدعاء الحمل الزائد المتخصص MyBase

نصائح أخرى

وفقا لمواصفات C # (7.4.3.2)، فإن الطريقة غير العامة هي أفضل من العام العام، لذلك يجب تحديدها.

ولكن، أعتقد أن عام واحد يتم التقاطه في قضيتك، لأنه يسمى ضمن سياق استدعاء عام ("foreach" حلقة).

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