تم إعداد ترجمة المقال خصيصًا لطلاب الدورة التدريبية "C # Developer" .

ما هي الأحداث في C #؟
يمكن استخدام الحدث لتقديم الإخطارات. يمكنك الاشتراك في الحدث إذا كنت بحاجة إلى هذه الإشعارات. يمكنك أيضًا إنشاء أحداث خاصة بك ستعلمك بوجود شيء يثير اهتمامك. يوفر .NET Framework أنواعًا مضمنة يمكنك استخدامها لإنشاء أحداث. باستخدام المفوضين وتعبيرات lambda والأساليب مجهولة ، يمكنك إنشاء واستخدام الأحداث بطريقة مريحة.
فهم المندوبين في C #
في C # ، يشكل المندوبون اللبنات الأساسية للأحداث. المفوض هو نوع يحدد توقيع الأسلوب. على سبيل المثال ، في C ++ ، يمكن القيام بذلك باستخدام مؤشر دالة. في C # ، يمكنك إنشاء مثيل لمفوض يشير إلى طريقة أخرى. يمكنك استدعاء هذه الطريقة من خلال المثيل المفوض.
فيما يلي مثال لإعلان المفوض واستدعاء طريقة من خلاله.
باستخدام المفوض في C #
}class Program { public delegate double MathDelegate(double value1, double value2); public static double Add(double value1, double value2) { return value1 + value2; } public static double Subtract(double value1, double value2) { return value1 - value2; } Console.ReadLine(); public static void Main() { MathDelegate mathDelegate = Add; var result = mathDelegate(5, 2); Console.WriteLine(result);
كما ترون ، نستخدم الكلمة الأساسية للمفوض لإعلام المترجم أننا بصدد إنشاء نوع المفوض.
من السهل إنشاء مثيل للمندوبين بالإضافة إلى الإنشاء التلقائي لنوع المفوض الجديد.
يمكنك أيضًا استخدام الكلمة الأساسية
الجديدة لإنشاء مفوض.
MathDelegate mathDelegate = new MathDelegate(Add)
؛
مفوض تم إنشاء مثيل له هو كائن؛ يمكنك أيضًا استخدامه وتمريرها كوسيطة إلى طرق أخرى.
الإرسال المتعدد في C #
ميزة أخرى رائعة للمندوبين هي أنه يمكنك الجمع بينهما. وهذا ما يسمى الإرسال المتعدد. يمكنك استخدام + أو + = عامل التشغيل لإضافة طريقة أخرى إلى قائمة المكالمات لمثيل المفوض الحالي. وبالمثل ، يمكنك أيضًا إزالة طريقة من قائمة المكالمات باستخدام مشغل تعيين التناقص (- أو - =). تعمل هذه الميزة كأساس للأحداث في C #. فيما يلي مثال لمفوض البث المتعدد.
class Program { static void Hello(string s) { Console.WriteLine(" Hello, {0}!", s); } static void Goodbye(string s) { Console.WriteLine(" Goodbye, {0}!", s); } delegate void Del(string s); static void Main() { Del a, b, c, d;
هذا ممكن لأن المندوبين يرثون من فئة
System.MulticastDelegate
، والذي يرث بدوره من
System.Delegate
. يمكنك استخدام الأعضاء المحددين في هذه الفئات الأساسية لمندوبيك.
على سبيل المثال ، لمعرفة عدد الطرق التي سيدعوها مفوض البث المتعدد ، يمكنك استخدام الكود التالي:
int invocationCount = d.GetInvocationList().GetLength(0);
التباين والتناقض في C #
عندما تقوم بتعيين طريقة لمفوض ، فلن يكون لتوقيع الطريقة مطابقة المفوض تمامًا. وهذا ما يسمى التباين ومخالفة. يسمح Covariance لطريقة الحصول على نوع إرجاع مشتق أكثر من النوع المحدد في المفوض. يسمح Contravariance لطريقة مع أنواع المعلمات التي يتم اشتقاقها أقل من الأنواع في المفوض.
مندوب التغاير
هنا مثال على التغاير ،
class Program { public delegate TextWriter CovarianceDel(); public static StreamWriter MethodStream() { return null; } public static StringWriter MethodString() { return null; } static void Main() { CovarianceDel del; del = MethodStream; del = MethodString; Console.ReadLine(); } }
نظرًا لأن كلا
StreamWriter
و
StringWriter
من
TextWriter
، يمكنك استخدام
CovarianceDel
بكلتا الطريقتين.
تناقض في المندوبين
فيما يلي مثال على المخالفة.
class Program { public static void DoSomething(TextWriter textWriter) { } public delegate void ContravarianceDel(StreamWriter streamWriter); static void Main() { ContravarianceDel del = DoSomething; Console.ReadLine(); } }
نظرًا لأن طريقة
DoSomething
يمكن أن تعمل مع
TextWriter
، فمن المؤكد أنها يمكن أن تعمل مع
StreamWriter
. بسبب المخالفة ، يمكنك الاتصال
DoSomething
وتمرير مثيل
StreamWriter
إلى طريقة
DoSomething
.
يمكنك معرفة المزيد عن هذا المفهوم
هنا .
تعبيرات لامدا في C #
في بعض الأحيان ، قد يتطلب توقيع الأسلوب بأكمله رمزًا أكثر من النص الأساسي للطريقة نفسها. هناك أيضًا مواقف تحتاج فيها إلى إنشاء طريقة كاملة لمجرد استخدامها كمفوض.
بالنسبة لهذه الحالات ، أضافت Microsoft بعض الميزات الجديدة في C # ، مثل الأساليب المجهولة في 2.0. في C # 3.0 ، أصبحت الأمور أفضل عندما تمت إضافة تعبيرات lambda. التعبير Lambda هو الطريقة المفضلة عند كتابة رمز جديد.
التالي مثال على بناء الجملة lambda.
class Program { public delegate double MathDelegate(double value1, double value2); public static void Main() { MathDelegate mathDelegate = (x,y) => x + y; var result = mathDelegate(5, 2); Console.WriteLine(result); // : 7 mathDelegate = (x, y) => x - y; ; result = mathDelegate(5, 2); Console.WriteLine(result); // : 3 Console.ReadLine(); } }
لقراءة هذا الرمز ، تحتاج إلى استخدام كلمة "يتبع" في سياق بناء جملة lambda الخاص. على سبيل المثال ، يقرأ تعبير lambda الأول في المثال أعلاه "x و y يتبعان إضافة x و y".
وظيفة لامدا ليس لها اسم محدد ، على عكس الطريقة. لهذا السبب ، تسمى lambdas وظائف مجهولة. لا تحتاج أيضًا إلى تحديد نوع قيمة الإرجاع بشكل صريح. المترجم يفترض ذلك تلقائيا من امدا الخاص بك. وفي حالة المثال أعلاه ، لا يتم أيضًا تحديد أنواع المعلمات x و y بشكل صريح.
يمكنك إنشاء lambdas التي تغطي العديد من العوامل. يمكنك القيام بذلك عن طريق إضافة الأقواس المتعرجة حول العبارات التي تشكل lambda ، كما هو موضح في المثال أدناه.
MathDelegate mathDelegate = (x,y) => { Console.WriteLine("Add"); return x + y; };
في بعض الأحيان ، يبدو الإعلان المفوض عن حدث مرهقًا بعض الشيء. لهذا السبب ، يحتوي .NET Framework على العديد من أنواع المفوض المضمنة التي يمكنك استخدامها عند تعريف المفوضين. في المثال MathDelegate ، استخدمت المفوض التالي:
public delegate double MathDelegate(double value1, double value2);
يمكنك استبدال هذا المفوض بأحد الأنواع المضمنة ، وهي
Func <int, int, int>
.
مثل هذا
class Program { public static void Main() { Func<int, int, int> mathDelegate = (x,y) => { Console.WriteLine("Add"); return x + y; }; var result = mathDelegate(5, 2); Console.WriteLine(result);
يمكن العثور على أنواع Func <...> في مساحة اسم النظام. وهي تمثل المفوضين الذين يعرضون نوعًا ويستغرقون من 0 إلى 16 معلمة. يتم توريث كل هذه الأنواع من System.MulticaseDelegate بحيث يمكنك إضافة طرق متعددة إلى قائمة المكالمات.
إذا كنت بحاجة إلى نوع تفويض لا يُرجع قيمة ، فيمكنك استخدام أنواع System.Action. يمكن أن تأخذ أيضًا من 0 إلى 16 معلمة ، لكن لا تُرجع قيمة.
فيما يلي مثال لاستخدام نوع الإجراء ،
class Program { public static void Main() { Action<int, int> mathDelegate = (x,y) => { Console.WriteLine(x + y); }; mathDelegate(5, 2);
يمكنك معرفة المزيد حول المفوضين المدمجين في .NET
هنا .
تزداد الأمور تعقيدًا عندما تبدأ وظيفة lambda في الإشارة إلى المتغيرات المعلنة خارج تعبير lambda أو إلى هذا. عادةً ، عندما يترك عنصر تحكم نطاق متغير ، يصبح المتغير غير صالح. ولكن ماذا لو أشار المفوض إلى متغير محلي. لإصلاح ذلك ، ينشئ المحول البرمجي تعليمة برمجية تعمل على إطالة عمر المتغير الذي تم التقاطه ، على الأقل طالما أن المفوض الأطول عمراً. وهذا ما يسمى إغلاق.
يمكنك معرفة المزيد عن عمليات الإغلاق
هنا .
الأحداث في C #
النظر في نمط التنمية الشعبية - الناشر المشترك (pub / sub). يمكنك الاشتراك في حدث ما ، ثم سيتم إخطارك عندما يبدأ ناشر الحدث بحدث جديد. يستخدم هذا النظام لتأسيس اتصال ضعيف بين المكونات في التطبيق.
المفوض يشكل الأساس لنظام الأحداث في C #.
الحدث هو نوع خاص من المفوضين يسهل البرمجة الموجهة نحو الحدث. الأحداث هي أعضاء في فئة لا يمكن استدعاؤها خارج الفصل ، بغض النظر عن محدد الوصول. لذلك ، على سبيل المثال ، فإن الحدث الذي تم إعلانه على أنه عام سيسمح للفئات الأخرى باستخدام + = و - = لهذا الحدث ، ولكن يُسمح بتشغيل حدث (أي استدعاء المفوض) فقط في الفصل الذي يحتوي على الحدث. لنلقِ نظرة على مثال ،
بعد ذلك ، يمكن لأي طريقة في فصل آخر الاشتراك في الحدث عن طريق إضافة إحدى طرقها إلى مفوض الحدث:
فيما يلي مثال يوضح كيف يمكن للفصل توفير مفوض مفتوح وإنشاء حدث.
class Program { static void Main(string[] args) {
حتى إذا تم إعلان الحدث على أنه عام ، فلا يمكن تشغيله مباشرة في أي مكان باستثناء في الفصل الذي يقع فيه.
باستخدام الكلمة الأساسية
event
، يحمي المترجم حقلنا من الوصول غير المرغوب فيه.
و كذلك
لا يسمح باستخدام = (مهمة المفوض المباشر). لذلك ، أصبح رمزك محميًا الآن من خطر حذف المشتركين السابقين باستخدام = بدلاً من + =.
بالإضافة إلى ذلك ، قد تلاحظ بناء جملة تهيئة حقل OnChange الخاص لمفوض فارغ ، مثل
delegate { }
. هذا يضمن أن حقل OnChange الخاص بنا ليس خاليًا أبدًا. لذلك ، يمكننا إزالة التحقق الفارغ قبل استدعاء الحدث إذا لم يكن هناك أعضاء آخرون في الفصل يجعلونه باطلاً.
عندما تقوم بتشغيل البرنامج أعلاه ، تنشئ الشفرة الخاصة بك مثيلًا جديدًا من Pub ، وتشترك في الحدث بطريقتين مختلفتين ، وتقوم بإنشاء حدث عن طريق الاتصال بـ p.Raise. فئة الحانة غير مدركة تمامًا لأي من المشتركين. انه يولد مجرد حدث.
يمكنك أيضًا قراءة مقالتي ،
C # Publisher-Subscriber Design Pattern ، لفهم أعمق لهذا المفهوم.
حسنا ، هذا كل شيء الآن. آمل أن تحصل على هذه الفكرة. شكرا لقراءة هذا المنصب. الرجاء إخبارنا إذا كانت هناك أي أخطاء أو تغييرات مطلوبة في التعليقات أدناه. شكرا مقدما!
روابط مفيدة
www.c-sharpcorner.com/blogs/c-sharp-generic-delegates-func-action-and-predicatedocs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/covariance-contravariancehttps://web.archive.org/web/20150707082707/http://diditwith.net/PermaLink،guid،235646ae-3476-4893-899d-105e4d48c25b.aspx