खोज…
परिचय
एक घटना एक सूचना है कि कुछ घटित हुआ है (जैसे कि माउस क्लिक) या, कुछ मामलों में, ऐसा होने वाला है (जैसे कि मूल्य परिवर्तन)।
कक्षाएं घटनाओं को परिभाषित कर सकती हैं और उनके उदाहरण (ऑब्जेक्ट) इन घटनाओं को बढ़ा सकते हैं। उदाहरण के लिए, एक बटन में एक क्लिक ईवेंट हो सकता है जो किसी उपयोगकर्ता द्वारा क्लिक किए जाने पर उठाया जाता है।
ईवेंट हैंडलर तब विधियां हैं जो तब मिलती हैं जब उनकी संबंधित घटना को उठाया जाता है। एक फॉर्म में प्रत्येक बटन के लिए क्लिक किया गया ईवेंट हैंडलर हो सकता है, उदाहरण के लिए।
पैरामीटर
पैरामीटर | विवरण |
---|---|
EventArgsT | वह प्रकार जो EventArgs से प्राप्त होता है और जिसमें ईवेंट पैरामीटर होते हैं। |
कार्यक्रम नाम | घटना का नाम। |
HandlerName | इवेंट हैंडलर का नाम। |
SenderObject | वह वस्तु जो घटना को आमंत्रित कर रही हो। |
EventArguments | EventArgsT प्रकार का एक उदाहरण जिसमें इवेंट पैरामीटर होते हैं। |
टिप्पणियों
एक घटना को बढ़ाते समय:
- हमेशा जांच लें कि क्या प्रतिनिधि
null
। एक अशक्त प्रतिनिधि का अर्थ है कि घटना का कोई सदस्य नहीं है। बिना किसी सब्सक्राइबर वाली घटना को उठाने सेNullReferenceException
।
- (उदाहरण के प्रतिनिधि कॉपी
EventName
) एक स्थानीय चर (जैसे कोeventName
/ बातिल के लिए जाँच घटना ऊपर उठाने से पहले)। यह बहु-पिरोया वातावरण में दौड़ की स्थिति से बचा जाता है:
गलत :
if(Changed != null) // Changed has 1 subscriber at this point
// In another thread, that one subscriber decided to unsubscribe
Changed(this, args); // `Changed` is now null, `NullReferenceException` is thrown.
अधिकार :
// Cache the "Changed" event as a local. If it is not null, then use
// the LOCAL variable (handler) to raise the event, NOT the event itself.
var handler = Changed;
if(handler != null)
handler(this, args);
-
if
एक कथन में ग्राहकों के लिए प्रतिनिधि को शून्य-जाँच करने के बजाय अशक्त-संचालक ऑपरेटर (?) का उपयोग करें:EventName?.Invoke(SenderObject, new EventArgsT());
- प्रतिनिधि प्रकारों की घोषणा करने के लिए एक्शन <> का उपयोग करते समय, अनाम विधि / घटना हैंडलर हस्ताक्षर घटना घोषणा में घोषित गुमनाम प्रतिनिधि प्रकार के समान होना चाहिए।
घोषणा और बढ़ती हुई घटनाएँ
एक घटना की घोषणा
आप निम्नलिखित सिंटैक्स का उपयोग करके किसी भी class
या struct
पर एक घटना की घोषणा कर सकते हैं:
public class MyClass
{
// Declares the event for MyClass
public event EventHandler MyEvent;
// Raises the MyEvent event
public void RaiseEvent()
{
OnMyEvent();
}
}
घटनाओं की घोषणा करने के लिए एक विस्तारित वाक्यविन्यास है, जहां आप इवेंट का एक निजी उदाहरण रखते हैं, और add
और set
एक्सेसर्स का उपयोग करके एक सार्वजनिक उदाहरण को परिभाषित करते add
। वाक्य रचना C # गुणों के समान है। सभी मामलों में, ऊपर दिखाए गए वाक्यविन्यास को प्राथमिकता दी जानी चाहिए, क्योंकि संकलक कोड को यह सुनिश्चित करने में मदद करता है कि एकाधिक थ्रेड्स आपकी कक्षा में ईवेंट हैंडलर्स को सुरक्षित रूप से जोड़ और हटा सकते हैं।
घटना को उठाना
private void OnMyEvent()
{
EventName?.Invoke(this, EventArgs.Empty);
}
private void OnMyEvent()
{
// Use a local for EventName, because another thread can modify the
// public EventName between when we check it for null, and when we
// raise the event.
var eventName = EventName;
// If eventName == null, then it means there are no event-subscribers,
// and therefore, we cannot raise the event.
if(eventName != null)
eventName(this, EventArgs.Empty);
}
ध्यान दें कि घटनाओं को केवल घोषित प्रकार द्वारा ही उठाया जा सकता है। ग्राहक केवल सदस्यता / सदस्यता समाप्त कर सकते हैं।
6.0 से पहले C # संस्करणों के लिए, जहां EventName?.Invoke
; EventName?.Invoke
समर्थित नहीं है, यह मंगलाचरण से पहले एक अस्थायी चर में घटना को असाइन करने के लिए एक अच्छा अभ्यास है, जैसा कि उदाहरण में दिखाया गया है, जो उन मामलों में थ्रेड-सुरक्षा सुनिश्चित करता है जहां कई थ्रेड्स एक ही निष्पादित होते हैं। कोड। ऐसा करने में विफल रहने से NullReferenceException
को कुछ मामलों में फेंक दिया जा सकता है जहां कई थ्रेड एक ही ऑब्जेक्ट उदाहरण का उपयोग कर रहे हैं। C # 6.0 में, संकलक कोड के समान है जो C # 6 के कोड उदाहरण में दिखाया गया है।
मानक घटना की घोषणा
घटना की घोषणा:
public event EventHandler<EventArgsT> EventName;
ईवेंट हैंडलर घोषणा:
public void HandlerName(object sender, EventArgsT args) { /* Handler logic */ }
घटना के लिए सदस्यता:
गतिशील रूप से:
EventName += HandlerName;
डिजाइनर के माध्यम से:
- कंट्रोल के गुण विंडो (लाइटनिंग बोल्ट) पर ईवेंट्स बटन पर क्लिक करें
- ईवेंट नाम पर डबल-क्लिक करें:
- दृश्य स्टूडियो घटना कोड उत्पन्न करेगा:
private void Form1_Load(object sender, EventArgs e)
{
}
विधि लागू करना:
EventName(SenderObject, EventArguments);
बेनामी इवेंट हैंडलर घोषणा
घटना की घोषणा:
public event EventHandler<EventArgsType> EventName;
लंबर ऑपरेटर => का उपयोग करके इवेंट हैंडलर घोषणा और घटना की सदस्यता:
EventName += (obj, eventArgs) => { /* Handler logic */ };
प्रतिनिधि अनाम विधि सिंटैक्स का उपयोग करके ईवेंट हैंडलर घोषणा:
EventName += delegate(object obj, EventArgsType eventArgs) { /* Handler Logic */ };
एक इवेंट हैंडलर की घोषणा और सदस्यता जो इवेंट के पैरामीटर का उपयोग नहीं करता है, और इसलिए पैरामीटर निर्दिष्ट करने की आवश्यकता के बिना उपरोक्त सिंटैक्स का उपयोग कर सकता है:
EventName += delegate { /* Handler Logic */ }
घटना को आमंत्रित करना:
EventName?.Invoke(SenderObject, EventArguments);
गैर-मानक घटना घोषणा
घटनाएँ किसी भी प्रतिनिधि प्रकार की हो सकती हैं, न कि केवल EventHandler
और EventHandler<T>
। उदाहरण के लिए:
//Declaring an event
public event Action<Param1Type, Param2Type, ...> EventName;
यह मानक EventHandler
घटनाओं के समान उपयोग किया जाता है:
//Adding a named event handler
public void HandlerName(Param1Type parameter1, Param2Type parameter2, ...) {
/* Handler logic */
}
EventName += HandlerName;
//Adding an anonymous event handler
EventName += (parameter1, parameter2, ...) => { /* Handler Logic */ };
//Invoking the event
EventName(parameter1, parameter2, ...);
फ़ील्ड और स्थानीय चर के साथ एक ही कथन में एक ही प्रकार की कई घटनाओं की घोषणा करना संभव है (हालांकि यह अक्सर एक बुरा विचार हो सकता है):
public event EventHandler Event1, Event2, Event3;
यह तीन अलग-अलग घटनाओं ( Event1
, Event2
और Event3
) को सभी प्रकार के EventHandler
घोषित करता है।
नोट: हालांकि कुछ संकलक इंटरफेस के साथ-साथ कक्षाओं में इस वाक्यविन्यास को स्वीकार कर सकते हैं, सी # विनिर्देश (v5.0 )13.2.3) उन इंटरफेस के लिए व्याकरण प्रदान करता है जो इसे अनुमति नहीं देते हैं, इसलिए इंटरफेस में इसका उपयोग करना विभिन्न कंपाइलरों के लिए अविश्वसनीय हो सकता है।
अतिरिक्त डेटा वाले कस्टम EventArgs बनाना
कस्टम ईवेंट को आमतौर पर ईवेंट के बारे में जानकारी वाले कस्टम ईवेंट तर्क की आवश्यकता होती है। उदाहरण के लिए MouseEventArgs
जो की तरह माउस घटनाओं से प्रयोग किया जाता है MouseDown
या MouseUp
घटनाओं, के बारे में जानकारी Location
या Buttons
जो घटना उत्पन्न करने के लिए इस्तेमाल किया।
नई ईवेंट बनाते समय, कस्टम ईवेंट arg बनाने के लिए:
-
EventArgs
से प्राप्त एक क्लास बनाएं और आवश्यक डेटा के लिए गुणों को परिभाषित करें। - एक सम्मेलन के रूप में, क्लास का नाम
EventArgs
साथ समाप्त होना चाहिए।
उदाहरण
नीचे दिए गए उदाहरण में, हम एक वर्ग की Price
संपत्ति के लिए एक PriceChangingEventArgs
घटना बनाते हैं। घटना डेटा वर्ग एक में शामिल है CurrentPrice
और एक NewPrice
। जब आप Price
संपत्ति के लिए एक नया मूल्य प्रदान करते हैं तो घटना बढ़ जाती है और उपभोक्ता को पता चलता है कि मूल्य बदल रहा है और उन्हें वर्तमान मूल्य और नई कीमत के बारे में जानने दें:
PriceChangingEventArgs
public class PriceChangingEventArgs : EventArgs
{
public PriceChangingEventArgs(int currentPrice, int newPrice)
{
this.CurrentPrice = currentPrice;
this.NewPrice = newPrice;
}
public int CurrentPrice { get; private set; }
public int NewPrice { get; private set; }
}
उत्पाद
public class Product
{
public event EventHandler<PriceChangingEventArgs> PriceChanging;
int price;
public int Price
{
get { return price; }
set
{
var e = new PriceChangingEventArgs(price, value);
OnPriceChanging(e);
price = value;
}
}
protected void OnPriceChanging(PriceChangingEventArgs e)
{
var handler = PriceChanging;
if (handler != null)
handler(this, e);
}
}
आप उपभोक्ता को नए मूल्य को बदलने की अनुमति देकर उदाहरण को बढ़ा सकते हैं और फिर मूल्य का उपयोग संपत्ति के लिए किया जाएगा। ऐसा करने के लिए यह इन परिवर्तनों को कक्षाओं में लागू करने के लिए पर्याप्त है।
NewPrice
की परिभाषा को NewPrice
लिए बदलें:
public int NewPrice { get; set; }
की परिभाषा बदले Price
का उपयोग करने के e.NewPrice
, संपत्ति के मूल्य के रूप में बुला के बाद OnPriceChanging
:
int price;
public int Price
{
get { return price; }
set
{
var e = new PriceChangingEventArgs(price, value);
OnPriceChanging(e);
price = e.NewPrice;
}
}
रद्द करने योग्य घटना बनाना
एक रद्द करने वाली घटना को एक वर्ग द्वारा उठाया जा सकता है जब वह एक कार्रवाई करने वाला होता है जिसे रद्द किया जा सकता है, जैसे कि Form
FormClosing
इवेंट।
ऐसी घटना बनाने के लिए:
-
CancelEventArgs
से व्युत्पन्न एक नया ईवेंट आर्ग बनाएं और ईवेंट डेटा के लिए अतिरिक्त गुण जोड़ें। -
EventHandler<T>
का उपयोग करके एक ईवेंट बनाएं और नए कैंसल ईवेंट arg वर्ग का उपयोग करें जो आपने बनाया था।
उदाहरण
नीचे दिए गए उदाहरण में, हम एक वर्ग की Price
संपत्ति के लिए एक PriceChangingEventArgs
घटना बनाते हैं। इवेंट डेटा वर्ग में एक Value
होता है जो उपभोक्ता को नए के बारे में बताता है। ईवेंट तब उठाया जाता है जब आप Price
प्रॉपर्टी को एक नया मूल्य प्रदान करते हैं और उपभोक्ता को पता चलता है कि मूल्य बदल रहा है और उन्हें ईवेंट रद्द करने दें। उपभोक्ता घटना को रद्द करता है, तो के लिए पिछले मान Price
उपयोग किया जाएगा:
PriceChangingEventArgs
public class PriceChangingEventArgs : CancelEventArgs
{
int value;
public int Value
{
get { return value; }
}
public PriceChangingEventArgs(int value)
{
this.value = value;
}
}
उत्पाद
public class Product
{
int price;
public int Price
{
get { return price; }
set
{
var e = new PriceChangingEventArgs(value);
OnPriceChanging(e);
if (!e.Cancel)
price = value;
}
}
public event EventHandler<PriceChangingEventArgs> PropertyChanging;
protected void OnPriceChanging(PriceChangingEventArgs e)
{
var handler = PropertyChanging;
if (handler != null)
PropertyChanging(this, e);
}
}
घटना के गुण
यदि कोई वर्ग बड़ी संख्या में आयोजन करता है, तो प्रति प्रतिनिधि एक क्षेत्र की संग्रहण लागत स्वीकार्य नहीं हो सकती है। .NET फ्रेमवर्क इन मामलों के लिए ईवेंट गुण प्रदान करता है। इस तरह आप इवेंट डेलिगेट्स को स्टोर करने के लिए EventHandlerList
जैसी अन्य डेटा संरचना का उपयोग कर सकते हैं:
public class SampleClass
{
// Define the delegate collection.
protected EventHandlerList eventDelegates = new EventHandlerList();
// Define a unique key for each event.
static readonly object someEventKey = new object();
// Define the SomeEvent event property.
public event EventHandler SomeEvent
{
add
{
// Add the input delegate to the collection.
eventDelegates.AddHandler(someEventKey, value);
}
remove
{
// Remove the input delegate from the collection.
eventDelegates.RemoveHandler(someEventKey, value);
}
}
// Raise the event with the delegate specified by someEventKey
protected void OnSomeEvent(EventArgs e)
{
var handler = (EventHandler)eventDelegates[someEventKey];
if (handler != null)
handler(this, e);
}
}
यह दृष्टिकोण व्यापक रूप से GUF फ्रेमवर्क जैसे WinForms में उपयोग किया जाता है जहां नियंत्रण में दर्जनों और यहां तक कि सैकड़ों घटनाएं हो सकती हैं।
ध्यान दें कि EventHandlerList
थ्रेड-सुरक्षित नहीं है, इसलिए यदि आप उम्मीद करते हैं कि आपकी क्लास कई थ्रेड्स से उपयोग की जाएगी, तो आपको लॉक स्टेटमेंट या अन्य सिंक्रोनाइज़ेशन मैकेनिज़म (या एक स्टोरेज का उपयोग करना होगा जो थ्रेड सुरक्षा प्रदान करता है)।