لماذا يجب أن تستغرق الأحداث في C# (المرسل، EventArgs)؟

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

  •  01-07-2019
  •  | 
  •  

سؤال

من المعروف أنه يجب عليك الإعلان عن الأحداث التي تتخذ كمعلمات (object sender, EventArgs args).لماذا؟

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

المحلول

يتيح ذلك للمطور المستهلك القدرة على كتابة معالج حدث واحد لأحداث متعددة، بغض النظر عن المرسل أو الحدث.

يحرر: لماذا تحتاج إلى نمط مختلف؟يمكنك وراثة EventArgs لتوفير أي قدر من البيانات، وتغيير النمط لن يؤدي إلا إلى إرباك وإحباط أي مطور مجبر على استهلاك هذا النمط الجديد.

نصائح أخرى

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

لأنه نمط جيد لأي آلية رد اتصال، بغض النظر عن اللغة.تريد معرفة من أرسل الحدث (المرسل) والبيانات ذات الصلة بالحدث (EventArgs).

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

وإلا فإن الاتساق ومبدأ الأقل مفاجأة يبرران استخدام EventArgs لتمرير البيانات.

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

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

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

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

يقول كريس أندرسون في كتاب إرشادات تصميم الإطار:

[T] هذا مجرد نمط.من خلال تجميع وسيطات الأحداث في الفصل الدراسي، يمكنك الحصول على دلالات إصدار أفضل.من خلال وجود نمط مشترك (sender, e) يمكن تعلمه بسهولة كتوقيع لجميع الأحداث.

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

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

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

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

لا أستطيع التفكير في طريقة أكثر ذكاءً للتعامل مع الأحداث.

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

أظن أن هذا السيناريو ينطبق على عدد كبير من الحالات وفي هذه الحالات تقل قيمة EventArgs بشكل كبير.

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

لنفترض أنك تريد تفويض التسجيل إلى حدث عام...دون كتابة الحدث الخاص بك، Args SUBCLASS.قد يبدو الأمر عديم الجدوى، لكني أحب استخدام الميزات الموجودة.يمكنك تمرير السلسلة الخاصة بك من خلال وسيطة الكائن، ولكن هذا يتعارض مع الاستخدام المقصود.حاول العثور على مرجع جيد للفئات الفرعية لـ EventArgs على Google، وستنتهي.(على الأقل فعلت.)

يساعد ReSharper قليلاً، لأنه عندما تكتب "EventArgs" سترى قائمة بجميع الفئات (ضمن نطاق الاستخدام/الاستيراد) التي تحتوي على السلسلة "EventArgs".من خلال الاطلاع على القائمة، سترى العديد من الفئات التي لا تحتوي على أعضاء سلسلة.عندما تصل الى ControlEventArgs, ، ترى أنه يمكن استخدام خاصية النص، ولكن مع كل الحمل الزائد لعنصر تحكم windows. ConvertEventArgs قد يكون مفيدًا، نظرًا لأنك تقوم بتمرير النوع مع البيانات، ولكن هذا لا يزال يتطلب اقترانًا محكمًا غير موثق جيدًا ولا آمن للكتابة بطبيعته. DataReceivedEventArgs لا يوجد لديه التنفيذ. إدخالWrittenEventArgs يتطلب EventLogEntry مع مصفوفة بايت أو StreamingContext للبيانات. ErrorEventArgs هو أقرب، مع رسالة استثناء، إذا كنت لا تمانع في استدعاء جميع أحداث السجل الخاصة بك Exception ErrorEvents داخليًا. FileSystemEventArgs ربما يكون هو الأقرب حتى الآن، مع سلسلتين ووسيطة تعداد WatcherChangeTypes المطلوبة التي يمكن تعيينها على 0، إذا كنت تعرف ما تفعله. تسميةEditEventArgs يستخدم int وسلسلة، إذا كنت لا تمانع في طلب مساحة الاسم Windows.Forms. RenamedEventArgs يشبه FileSystemEventArgs بسلسلة إضافية.أخيراً، ResolveEventArgs في System.Runtime.InteropServices يمرر سلسلة واحدة.هناك مكتبات أخرى، لكنني تمسكت ببعض المكتبات الأكثر شيوعًا.لذا، اعتمادًا على التنفيذ الذي يمكنني استخدامه ErrorEventArgs, FileSystemEventArgs أو ResolveEventArgs للتسجيل.

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