Olayları bildirmenin tercih edilen yolu


14

.NET olay modeli hakkındaki anlayışımdan oldukça memnunum. Sanırım sistemin küçük bir nüansını yanlış anlıyor olabilirim.

Olayları sınıflarıma koymaya başladığımda standart yolu şöyle kullanırdım:

public event EventHandler<MyEventArgs> MyEvent;

Bu, etkinliğe abone olan her şeyin aşağıdaki gibi bir yönteme ihtiyacı olacağı anlamına geliyordu:

void HandleThatEvent(object sender, MyEventArgs args){...}

Hangi güzel, ama nadiren gönderen umurumda olduğunu buldum, bu yüzden şişirilmiş yöntem imzaların bir sürü yaptı.

Bu yüzden kendi delege türlerimi beyan etmeye geçtim

public delegate void MyEventHandler(SomeClass argument);

Bu, dağınıklığı azalttı, ancak işleyicileri yazmaya geldiğinde bana küçük bir sorun bıraktı:

eventImplmentor.MyEvent += HandleThatEvent;
.
.
.
void HandleThatEvent(/*oh, um, what arguments does it take? Intellisense isn't telling me*/)

Bu yüzden temsilci beyanına geri dönüp bakıp sonra geri dönüp bunları yazmam ya da derlemem ve söylenmeyi beklemem gerekecekti.

Yani şimdi bunun yerine, sadece kullanıyorum Action, Action<T>ya da her türlü şablon uyuyor.

public event Action<SomeClass> MyEvent;

Böylece olayın üzerine gelebilir ve hangi parametreleri beklediğini söyleyebilirim.

Benim sorum, tüm bunlardan sonra: C # olayları bildirmek için en iyi uygulama var mı? Geri dönmeli miyim EventHandler<T>, yoksa Action<T>kabul edilebilir mi?


İşleyicinin olayı başlattığınız yere yerel olarak kopyalandığından emin olun, iş parçacığı güvenliği için bunu her zaman yapmak istersiniz.
Snoop

Kendi akıllı, ortalama ve yalın tipte güvenli olaylarınızı kapsüllenmiş kodda yazabilirsiniz, ancak yayınladığınız her şey standart kalıbı takip etmelidir, yoksa sadece sınıfınızın kullanıcılarını (ve görünüşe göre bazı araçları da) karıştırır.
Martin Maat

Yanıtlar:


8

Basit, dahili olay işleme için, basitçe Actionveya Action<T>teklif ettiğiniz gibi kullanılanlar vardır. Dahili olaylar için bile Gönderen dahil standart kalıbı kullanma eğilimindeyim, çünkü daha sonra ne zaman bir sınıf veya olayı ortaya çıkarmak isteyeceğinizi asla bilemezsiniz ve olay yöntemini yeniden yapmak zorunda kalmanın cezasını istemem herkese açık.

Olay işleme imzasının basit senaryolar için olması gerekenden biraz daha ağır olduğunu kabul ediyorum, ancak zamanla ek olay argümanları gerekli olabileceğinden artan geçişi işlemek için iyi tasarlanmış. Genel olarak, özellikle de belirttiğiniz gibi, yalnızca uygun IntelliSense desteğini aldığınız için standart desene sadık kalacağım.

Değeri için, bu biraz zaman koymak ve farklı bir olay işleme deseni ile geldi: .NET Olay İmzası - Güçlü Yazılan 'Gönderen' kullanarak? . Buradaki amaç, Göndereni kaldırmak TSenderdeğil, zayıf olarak yazmak yerine genel olarak güçlü yazılmasını sağlamaktı System.Object. Çok iyi çalışıyor; ancak bunu yaptığınızda IntelliSense desteğini kaybedersiniz, bu yüzden talihsiz bir değiş tokuş vardır.

Genel olarak, standart kalıba sadık kalacağım, ancak bunu yapmanın potansiyel olarak daha iyi yolları hakkında düşünmek ilginç.


Beni SO sorunuza yönlendirdiğiniz için teşekkürler. Bu çok ilginç. Gönderenin zorunlu olmasının neden bu kadar önemli olduğunu hala anlamıyorum. Çoğu zaman göndereni umursamıyorum. Sadece keyfi bir MS kuralı mı?
Matt Ellen

Hayır, elbette delegelerinizi istediğiniz gibi ilan edebilirsiniz. Göndereni her zaman dahil etmek .NET politikasıdır ve bu tamamen kötü bir fikir değildir.
Neil

@Neil: Bazen yararlı olduğunu anlıyorum, ama her zaman bunu yapma politikasını alamıyorum - özellikle MS olayları kendi yollarıyla yapmayı önerdiğinden. Olaylar hakkında gerçekten sevdiğim şeylerden biri sınıfları ayırma yeteneğidir. Nesneyi dahil edersem, tekrar birleştirilir. Sadece bir CLS uyumluluk şeyiyse, bununla yaşayabilirim.
Matt Ellen

Yalnızca gönderen nesnesini kullanırsanız tekrar birleştirilir, aksi takdirde kullanmadığınız için gönderenin değeri olarak neyin konulduğu önemli değildir. Bağımlılık, yalnızca bir bağımlılık olması gerektiğinde mevcuttur. Nereden geldiğini görüyorum ve nesne gönderen gezegendeki herhangi bir sunucudan tüm kodlardan kaybolduysa, geceleri kalmazdım.
Neil

Evet, gerçekten isterseniz gönderen olarak 'null' gönderebilirsiniz ... Ancak, Göndereni ekleyerek, olay işleyicinin kendisi isterse aboneliğini iptal edebilir. Genel olarak, etkinliğin kaynağını bilmenin genellikle oldukça önemli olduğunu söyleyebilirim.
Mike Rosenblum
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.