هل يمكن لأحد أن يقطر إلى اللغة الإنجليزية المناسبة ما هو المندوب؟

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

  •  23-09-2019
  •  | 
  •  

سؤال

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

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

المحلول

في أبسط المصطلحات الممكنة ، إنه مؤشر في الأساس طريقة.

يمكن أن يكون لديك متغير يحمل نوعًا مندوبًا (تمامًا كما سيكون لديك متغير int يمكنه الاحتفاظ بنوع int). يمكنك تنفيذ الطريقة التي يشير إليها المندوب من خلال استدعاء متغيرك كدالة.

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

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

نصائح أخرى

لدي وظيفة:

public long GiveMeTwoTimesTwo()
{
    return 2 * 2;
}

هذه الوظيفة تمتص. ماذا لو أريد 3 * 3؟

public long GiveMeThreeTimesThree()
{
    return 3 * 3;
}

الكثير من الكتابة. أنا كسول!

public long SquareOf(int n)
{
    return n * n;
}

لي SquareOf الوظيفة لا تهتم ماذا n هو. ستعمل بشكل صحيح لأي n مرت في. لا يعرف بالضبط ما الرقم n هو ، ولكن هو يفعل إعلم أن n هو عدد صحيح. لا يمكنك المرور "Haha not an integer" داخل SquareOf.

ها هي وظيفة أخرى:

public void DoSomethingRad()
{
    int x = 4;
    long y = SquareOf(x);
    Console.WriteLine(y);
}

على عكس اسمها ، فإن DosomethingRad لا يفعل أي شيء في الواقع. ومع ذلك ، فإنه يكتب squareof (4) وهو 16. هل يمكننا تغييره ليكون أقل مملًا؟

public void DoSomethingRad(int numberToSquare)
{
    long y = SquareOf(numberToSquare);
    Console.WriteLine(y);
}

DoSomethingRad من الواضح أنه لا يزال فشلًا جدًا. ولكن على الأقل يمكننا الانتقال إلى رقم إلى مربع ، لذلك لن يكتب 16 في كل مرة. (سوف يكتب 1 أو 4 أو 9 أو 16 أو ... Zzzz لا يزال مملاً نوعًا ما).

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

في مزيد من التفتيش ، يبدو أن الجزء الوحيد من SquareOf الذي - التي DoSomethingRad يهتم به هو أنه يمكننا منحها عددًا صحيحًا (numberToSquare) وأنه يعطينا long (لأننا وضعنا قيمة الإرجاع في y و y هو long).

public long CubeOf(int n)
{
    return n * n * n;
}

public void DoSomethingLeet(int numberToSquare)
{
    long y = CubeOf(numberToSquare);
    Console.WriteLine(y);
}

انظر كيف تشبه DoSomethingLeet هو ل DoSomethingRad؟ إذا كان هناك طريقة للانتقال سلوك (DoX()) بدلا من مجرد البيانات (int n)...

حتى الآن إذا أردنا كتابة مربع من الرقم ، يمكننا DoSomethingRad وإذا أردنا أن نكتب المكعب من الرقم ، يمكننا DoSomethingLeet. لذلك إذا أردنا كتابة الرقم الذي تم طرحه من 69 ، فهل يتعين علينا عمل طريقة أخرى ، DoSomethingCool؟ لا ، لأن هذا يتطلب الكثير من الكتابة (والأهم من ذلك ، فإنه يعيق قدرتنا على تغيير السلوك المثير للاهتمام عن طريق تغيير جانب واحد فقط من برنامجنا).

لذلك وصلنا إلى:

public long Radlicious(int doSomethingToMe, Func<int, long> doSomething)
{
    long y = doSomething(doSomethingToMe);
    Console.WriteLine(y);
}

يمكننا أن نسمي هذه الطريقة عن طريق كتابة هذا:

Radlicious(77, SquareOf);

Func<int, long> هو نوع خاص من المندوب. إنه يخزن السلوك الذي يقبل الأعداد الصحيحة والبصق longس. لسنا متأكدين من الطريقة التي تشير إليها ستفعل مع أي عدد صحيح معين نمر به ؛ كل ما نعرفه هو أنه ، مهما حدث ، سنحصل على ملف long الى الخلف.

ليس علينا أن نعطي أي معلمات ل SquareOf لان Func<int, long> يصف سلوك, ، وليس البيانات. الدعوة Radlicious(77, SquareOf) فقط يعطي السلوك العام للسلوك العام SquareOf ("آخذ رقمًا وأرجع مربعه") ، وليس ماذا SquareOf سوف تفعل لأي محدد عدد صحيح.

الآن إذا كنت قد فهمت ما أقوله ، فأنت بالفعل قد أبرمني ، لأنني أنا نفسي لا أحصل على هذه الأشياء حقًا.

* الجواب النهائي ، ابدأ في التجول في حماقة *

أعني ، يبدو الأمر intيمكن اعتبار S سلوكًا مملًا حقًا:

static int Nine()
{
    return 9;
}

ومع ذلك ، يبدو أن الخط الفاصل بين البيانات والسلوك ضبابية ، مع ما يُنظر إليه عادة على أنه بيانات هو ببساطة سلوك مملة.

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

حسنًا ، يبدو أن تجريدنا قد استعادنا طوال الطريق إلى المربع الأول. لدينا سلوك مجردة لذلك يتطلب رمز المصدر بأكمله لبرنامجنا لتحديد ما ستفعله. هذا سلوك غير محدد تمامًا: يمكن أن تفعل الوظيفة اى شى, ، ولكن يجب تزويدها مع كل شىء لتحديد ما يفعله. من ناحية أخرى ، يحدد السلوك تمامًا ، مثل Nine(), ، لا يحتاج إلى أي معلومات إضافية ، ولكن لا يمكنك فعل أي شيء آخر غير العودة 9.

وماذا في ذلك؟ لا أعلم.

المندوب هو مؤشر لطريقة. يمكنك بعد ذلك استخدام مندوبتك كمعلمة ذات طرق أخرى.

هنا هو رابط إلى برنامج تعليمي بسيط.

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

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

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

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

إنه ببساطة يشير إلى طريقة. أنها تأتي في استخدام كبير مع العمل مع Cross Threading.

فيما يلي مثال على الكود الخاص بي.

 //Start our advertisiment thread
    rotator = new Thread(initRotate);
    rotator.Priority = ThreadPriority.Lowest;
    rotator.Start();

    #region Ad Rotation
    private delegate void ad();
    private void initRotate()
    {
        ad ad = new ad(adHelper);
        while (true)
        {
            this.Invoke(ad);
            Thread.Sleep(30000);
        }

    }

    private void adHelper()
    {
        List<string> tmp = Lobby.AdRotator.RotateAd();
        picBanner.ImageLocation = @tmp[0].ToString();
        picBanner.Tag = tmp[1].ToString();            
    }
    #endregion

إذا لم تستخدم مندوبًا ، فلن تتمكن من عبور الوظيفة والاتصال بوظيفة Lobby.adrotator.

كما قال آخرون ، فإن المندوب هو إشارة إلى وظيفة. واحدة من أكثر الاستخدامات فائدة (IMO) هي الأحداث. عندما تقوم بتسجيل حدث ، تقوم بتسجيل وظيفة للحدث للاستدعاء ، والمندوبين مثاليون لهذه المهمة.

بعبارات أساسية ، فإن المندوب هو مجرد متغير يحتوي على (إشارة إلى) وظيفة. المندوبون مفيدون لأنهم يسمحون لك بتمرير وظيفة كمتغير دون أي قلق بشأن "حيث" جاءت الوظيفة بالفعل.

من المهم أن نلاحظ ، بالطبع ، أن الوظيفة لا يتم نسخها عندما يتم تجميعها في متغير ؛ انها مجرد ملزمة بالرجوع إليها. علي سبيل المثال:

class Foo
{
    public string Bar
    {
        get;
        set;
    }

    public void Baz()
    {
        Console.WriteLine(Bar);
    }
}

Foo foo = new Foo();
Action someDelegate = foo.Baz;

// Produces "Hello, world".
foo.Bar = "Hello, world";
someDelegate();

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

نفس الشيء ينطبق على الكود. المندوب هو نوع ، وهو كائن قادر على تنفيذ الطريقة.

على سبيل المثال.

Class Person
{
   public string GetPersonName(Person person)
   {
     return person.FirstName + person.LastName;
   }

   //Calling the method without the use of delegate
   public void PrintName()
   {
      Console.WriteLine(GetPersonName(this));
   }

   //using delegate
   //Declare delegate which matches the methods signature
   public delegate string personNameDelegate(Person person);

  public void PrintNameUsingDelegate()
  {
      //instantiate
      personNameDelegate = new personNameDelegate(GetPersonName);

      //invoke
      personNameDelegate(this);
  }

}

تسمى طريقة getPersonname باستخدام كائن المفوض الشخصي. بدلاً من ذلك ، يمكننا الحصول على طريقة printNameusingDelegate لأخذ مندوب كمعلمة.

public void PrintNameUsingDelegate(personNameDelegate pnd, Person person)
{
   pnd(person);
}

الميزة هي إذا أراد شخص ما طباعة الاسم على أنه lastName_FirstName ، فيجب عليه فقط لف هذه الطريقة في conshamedelegate والانتقال إلى هذه الوظيفة. لا يلزم تغيير رمز آخر.

المندوبون مهمون على وجه التحديد في

  1. الأحداث
  2. مكالمات غير متزامنة
  3. LINQ (مع تعبيرات Lambda)

إذا كنت ستنقل مهمة لشخص ما ، فسيكون المندوب هو الشخص الذي يتلقى العمل.

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

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

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

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