سؤال

نحن جميعا على دراية الرعب الذي هو C# الحدث الإعلان.لضمان موضوع السلامة ، المعيار هو أن أكتب شيئا مثل هذا:

public event EventHandler SomethingHappened;
protected virtual void OnSomethingHappened(EventArgs e)
{            
    var handler = SomethingHappened;
    if (handler != null)
        handler(this, e);
}

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

static public class EventExtensions
{
    static public void RaiseEvent(this EventHandler @event, object sender, EventArgs e)
    {
        var handler = @event;
        if (handler != null)
            handler(sender, e);
    }
    static public void RaiseEvent<T>(this EventHandler<T> @event, object sender, T e)
        where T : EventArgs
    {
        var handler = @event;
        if (handler != null)
            handler(sender, e);
    }
}

مع هذه طرق الإرشاد في مكان ، كل ما عليك أن تعلن رفع الحدث هو شيء من هذا القبيل:

public event EventHandler SomethingHappened;

void SomeMethod()
{
    this.SomethingHappened.RaiseEvent(this, EventArgs.Empty);
}

سؤالي:هل هذه فكرة جيدة ؟ هل نحن في عداد المفقودين أي شيء بسبب عدم وجود معيار على طريقة ؟ (شيء واحد أنا لاحظت أنه لا يعمل مع الأحداث التي الصريحة إضافة/إزالة رمز.)

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

المحلول

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

ومع ذلك ، هناك طريقة أسهل لعمل ذلك مؤشر الترابط-الآمن - تهيئة مع عدم المرجع معالج:

public event EventHandler SomethingHappened = delegate {};

ضرب أداء الدعوة إضافية مندوب ستكون ضئيلة ، وهذا بالتأكيد يجعل رمز أسهل.

بالمناسبة, في طريقة التمديد لا تحتاج متغير محلي يمكنك القيام به:

static public void RaiseEvent(this EventHandler @event, object sender, EventArgs e)
{
    if (@event != null)
        @event(sender, e);
}

static public void RaiseEvent<T>(this EventHandler<T> @event, object sender, T e)
    where T : EventArgs
{
    if (@event != null)
        @event(sender, e);
}

أنا شخصيا لن تستخدم الكلمة كمعلمة اسم لكن ذلك لا يغير الدعوة إلى جنب في كل شيء ، حتى تفعل ما تريد :)

تحرير:أما بالنسبة "OnXXX" الطريقة:هل تخطط الفصول الدراسية كونها مشتقة من ؟ وفي رأيي أن معظم الطبقات يجب أن تكون مختومة.إذا كنت هل, هل تريد تلك الفئات المشتقة أن تكون قادرة على رفع الحدث ؟ إذا كانت الإجابة على أي من هذه الأسئلة هي "لا" ثم لا يكلف نفسه عناء.إذا كان الجواب على كل "نعم" ثم لا :)

نصائح أخرى

الآن C# 6 هنا ، هناك أكثر إحكاما ، مؤشر الترابط-الآمن الطريق إلى النار الحدث:

SomethingHappened?.Invoke(this, e);

Invoke() إلا إذا دعا المندوبين يتم تسجيل الحدث (أيانها ليست null), بفضل null-الشرطي المشغل, "?".

خيوط المشكلة "معالج" التعليمات البرمجية في السؤال تحدد حل هو تجنب هنا لأن مثل هذا الرمز ، SomethingHappened هو فقط الوصول إليها مرة واحدة, حتى لا يكون هناك أي إمكانية تعيين إلى null بين الاختبار و الاحتجاج.

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

[وهنا فكر]

مجرد كتابة رمز مرة واحدة في الطريقة الموصى بها وينبغي القيام به معها.ثم لا تخلط بين زملائك يبحث على رمز التفكير فعلت شيئا خاطئا ؟

[قرأت المزيد من المشاركات تحاول أن تجد طرق كتابة معالج الحدث مما كنت تنفق أي وقت مضى كتابة معالج الحدث.]

رمز أقل وأكثر قابلية للقراءة.لي تحب.

إذا كنت لا ترغب في أداء يمكنك أن يعلن هذا الحدث الخاص بك مثل هذا لتجنب null تحقق:

public event EventHandler SomethingHappened = delegate{};

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

أنت تنقذ نفسك من مرجع فارغة استثناء ، ولكن هناك أسهل الطرق للقيام بذلك, كما جون السكيت و cristianlibardo أشار في إجاباتهم.

شيء آخر هو أن غير مختومة الطبقات ، OnFoo الطريقة الافتراضية التي لا أعتقد أن من الممكن مع طرق الإرشاد.

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