لا يمكن استخدام أساليب الامتداد المحددة في أنواع القيم لإنشاء مفوضين - لماذا لا؟

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

سؤال

يمكن تعيين أساليب الامتداد للمفوضين الذين يطابقون استخدامهم للكائن، مثل هذا:

static class FunnyExtension {
    public static string Double(this string str) { return str + str; }
    public static int Double(this int num) { return num + num; }
}


Func<string> aaMaker = "a".Double;
Func<string, string> doubler = FunnyExtension.Double;

Console.WriteLine(aaMaker());       //Prints "aa"
Console.WriteLine(doubler("b"));    //Prints "bb"

إذا كان النوع الذي يقومون بتوسيعه هو نوع قيمة، فلن يعمل:

Func<int> eightMaker = 4.Double;    //Error CS1113: Extension methods 'FunnyExtension.Double(int)' defined on value type 'int' cannot be used to create delegates
Func<int, int> intDoubler = FunnyExtension.Double;  //Works

هذا يعطي

خطأ CS1113:طرق التمديد 'FunnyStension.double (int) "المحددة على نوع القيمة" int "لا يمكن استخدامها لإنشاء مندوبين.

لماذا لا يستطيعون؟

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

المحلول

ردًا على إجابتي الأخرى، يلاحظ إريك سميث بشكل صحيح:

"...لأنه يتطلب ضمنيًا تحديد معلمة نوع جهاز الاستقبال ...".وهذا ما يحدث على أي حال، إذا قمت بشيء مثل هذا:Func f = 5.ToString;وهو أمر قانوني تمامًا.

قادني التفكير في هذا إلى إجابة جديدة.جرب هذا للحجم:

تأخذ أساليب "المثيل" العادية على البنيات، على مستوى CIL، "مؤشرًا مُدارًا" (اكتب &) كمعلمة جهاز الاستقبال.يعد ذلك ضروريًا حتى تتمكن أساليب المثيل الموجودة في البنيات من تعيين حقول البنية.يرى القسم الثاني، القسم 13.3.

وبالمثل، تأخذ أساليب المثيل في الفئات "مرجع كائن" (type O) كمعلمة جهاز استقبال (الفرق هو أن هذا مؤشر إلى الكومة المُدارة، ويجب تتبعه لـ GC).

منذ كلا CIL &رمل Oيمكن (ويتم) تنفيذ s بواسطة المؤشرات، كل شيء جيد جدًا بالنسبة لتنفيذ المفوض.بغض النظر عما إذا كان المفوض يلتقط طريقة ثابتة، أو طريقة مثيل فئة، أو طريقة مثيل بنية، فكل ما يحتاج إليه هو تمرير المؤشر إلى مكانه _target إلى الوسيطة الأولى للوظيفة.

لكن السيناريو الذي نناقشه يفسد ذلك.طريقة تمديد ثابتة تأخذ int كوسيطة أولى تتطلب وسيطة CIL من النوع int32 (انظر القسم الثالث، القسم 1.1.1). هنا حيث تخرج الأمور عن القضبان. لا أرى أي سبب لعدم حدوث ذلك ممكن ليدرك المندوبون أن هذا كان يحدث (على سبيل المثال، عن طريق فحص بيانات التعريف المرتبطة بـ MethodInfo التي يتم التقاطها) وإصدار صوت thunk من شأنه أن يفتح علبة _target وتمرير ذلك كحجة أولى، ولكن هذا ليس ضروريًا للمفوضين إلى أساليب المثيلات الكلاسيكية في البنيات، حيث أنهم يتوقعون مؤشرًا على أي حال ولا يبدو (إذا حكمنا من خلال المثال في إجابتي السابقة غير الصحيحة) ليتم تنفيذه.من الواضح أن نوع القيمة المحددة المعني سيتحكم في طبيعة thunk المطلوبة.

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

نصائح أخرى

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

إبداعي

لأنه سيتطلب ضمنيًا وضع علامة على معلمة جهاز الاستقبال من نوع القيمة (لأن الحقل _target في النوع System.Delegate الذي يحمل معلمة جهاز الاستقبال هو من النوع System.Object)، مما قد يؤدي إلى بعض سلوكيات الاسم المستعار الغريبة إذا لم تكن تتوقع هو - هي.

يحرر

هناك شيء آخر يحدث هنا.لقد قمت بتشغيل نموذج البرنامج هذا:

class Program
{
    public static int Combine(int a, int b)
    {
        return a + b;
    }

    static void Main(string[] args)
    {
        var combineMethod = typeof(Program).GetMethod("Combine");
        var add4 = Delegate.CreateDelegate(
                              typeof(Converter<int, int>),
                              4,
                              combineMethod) as Converter<int, int>;

        for (int i = 0; i < 10; i++)
        {
            Console.WriteLine(add4(i));
        }
        Console.ReadLine();
    }
}

وحصلت على ArgumentException:"خطأ في ربط الطريقة المستهدفة." في المكالمة إلى Createlegate.لست متأكدا من السبب، ولأن الطريقة ذات الصلة هي internalcall الطريقة، العاكس لا يساعد كثيرا.ال وثائق لCreateDelegate كما لم يكن الكثير من المساعدة.أنا متأكد من أن الأمر يتعلق بملاكمة جهاز الاستقبال، ربما يمكن لأي شخص لديه معرفة بمصدر الدوار أن يساعد في شرح السبب؟

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