[C #] events,

Source: Internet
Author: User

[C #] events,

The CLR event mode is based on the delegate, which is a type of safe method for calling the callback method.

I personally think that an event is essentially a delegate, so I figured out the delegate, as long as I knew the basic syntax of the event, it would be used (if it is thread-safe, I personally think this should be discussed with the thread ), therefore, this article only provides a simple time to introduce and write some code I have seen or used.

EventHandler

  

public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);

The above is the source code of C #, Which is ultra-simple (or delegated ).

There are two types:

1. Object sender: Event Source

2. TEventArgs e: Generic. Here you can customize the additional parameters required by the event.

  

Now that we know the basic syntax, let's look at how to write it.

Internal sealed class NewMailEventArgs: EventArgs {private readonly String m_from, m_to, m_subject; public NewMailEventArgs (String from, String to, String subject) {m_from = from; m_to =; m_subject = subject;} public String From {get {return m_from ;}} public String To {get {return m_to ;}} public String Subject {get {return m_subject ;}}}View Code

Here we define another class NewMailEventArgs. Note that EventArgs is inherited here, and all the class of event parameters must inherit this parent class. Here are all the parameters used by the callback function.

Internal class MailManager {public event EventHandler <NewMailEventArgs> NewMail; protected virtual void OnNewMail (NewMailEventArgs e) {if (NewMail! = Null) NewMail (this, e );}}View Code

A NewMail event is defined here. The EventHandler parameter type is NewMailEventArgs (which is the custom parameter class). We usually write the call method in the same class, it starts with "On" and ends with the event name. But there is a very dangerous thing here, that is, when multithreading is used, if the subscription is canceled in other places during execution, it will become NULL again, so it can be changed

 

Internal class MailManager {public event EventHandler <NewMailEventArgs> NewMail; protected virtual void OnNewMail (NewMailEventArgs e) {e. raise (this, ref NewMail);} public void SimulateNewMail (string from, string to, string subject) {var e = new NewMailEventArgs (from, to, subject ); onNewMail (e) ;}} public static class EventArgExtensions {public static void Raise <TEventArgs> (this TEventArgs e, Object sender, ref EventHandler <TEventArgs> eventDelegate) where TEventArgs: EventArgs {EventHandler <TEventArgs> temp = Interlocked. CompareExchange (ref eventDelegate, null, null); if (temp! = Null) temp (sender, e );}}View Code

Here I am used to it, and it is also recommended in the CLR book. It is used as an extended EventArgExtensions class for general Args: Mainly used for thread security and callback function execution (I think this is relatively simple, to encapsulate it, you only need to modify it. Remember that this is a common event call. If you have special requirements, do not add them. You can process them in special places ), interlocked. for more information about CompareExchange, see the official documentation. This document is used for lightweight thread synchronization and comparison.

 

Static void Main (string [] args) {var mail = new MailManager (); mail. newMail + = mail_NewMail; mail. simulateNewMail ("a", "B", "c"); mail. newMail-= mail_NewMail; Console. readKey ();} static void mail_NewMail (object sender, NewMailEventArgs e) {Console. writeLine (e. from); Console. writeLine (e. to); Console. writeLine (e. subject );}View Code

Finally, we subscribe to the event in the Main method (mail. NewMail + = mail_NewMail; here, we will directly + = and press the two Tab keys, and we will release it ourselves) and cancel the subscription with-=. Is it easy? The basic events have been completed.


Next, let's take a look at the final piece of EventSet Code provided by CLR. (This code is also my big love. We can manage events in a centralized manner and won't let the events fly everywhere. If you like it, you can study it, I will not introduce it more here. There are still many errors in the provided code, such as null pointers and no judgment on whether there is a key, but the ideas in it are indeed worth learning)

Public sealed class EventKey: object {}///////////////////////////////////// //////////////////////////////////////// // public sealed class EventSet {// The private dictionary used to maintain EventKey-> Delegate mappings private readonly Dictionary <EventKey, delegate> m_events = new Dictionary <EventKey, Delegate> (); // Adds an EventKey-> Delegate mapping if it doesn't exist or // combines a dele Gate to an existing EventKey public void Add (EventKey eventKey, Delegate handler) {Monitor. enter (m_events); Delegate d; m_events.TryGetValue (eventKey, out d); m_events [eventKey] = Delegate. combine (d, handler); Monitor. exit (m_events);} // Removes a delegate from an EventKey (if it exists) and // removes the EventKey-> Delegate mapping the last delegate is removed public void Remove (EventKey even TKey, Delegate handler) {Monitor. enter (m_events); // Call TryGetValue to ensure that an exception is not thrown if // attempting to remove a delegate from an EventKey not in the set Delegate d; if (m_events.TryGetValue (eventKey, out d) {d = Delegate. remove (d, handler); // If a delegate remains, set the new head else remove the EventKey if (d! = Null) m_events [eventKey] = d; else m_events.Remove (eventKey);} Monitor. exit (m_events);} // Raises the event for the indicated EventKey public void Raise (EventKey eventKey, Object sender, EventArgs e) {// Don't throw an exception if the EventKey is not in the set Delegate d; Monitor. enter (m_events); m_events.TryGetValue (eventKey, out d); Monitor. exit (m_events); if (d! = Null) {// Because the dictionary can contain several different delegate types, // it is impossible to construct a type-safe call to the delegate at // compile time. so, I call the System. delegate type's DynamicInvoke // method, passing it the callback method's parameters as an array of // objects. internally, DynamicInvoke will check the type safety of the // parameters with the callback method being called and call the method. // If there is a type mismatch, then DynamicInvoke will throw an exception. d. dynamicInvoke (new Object [] {sender, e });}}}View Codepublic class FooEventArgs: EventArgs {}// Define the EventArgs-derived type for this event. public class BarEventArgs: eventArgs {}///////////////////////////////////// //////////////////////////////////////// // internal class TypeWithLotsOfEvents {// Define a private instance field that references a collection. // The collection manages a set of Event/Delegate pairs. // NOTE: The EventSet type is not part of the FCL, it is my own type. private readonly EventSet m_eventSet = new EventSet (); // The protected property allows derived types access to the collection. protected EventSet {get {return m_eventSet ;}# region Code to support the Foo event (repeat this pattern for additional events) // Define the members necessary for the Foo event. // 2a. construct a static, read-only object to identify this event. // Each object has its own hash code for looking up this // event's delegate linked list in the object's collection. protected static readonly EventKey s_fooEventKey = new EventKey (); // 2d. define the event's accessor methods that add/remove the // delegate from the collection. public event EventHandler <FooEventArgs> Foo {add {m_eventSet.Add (s_fooEventKey, value);} remove {m_eventSet.Remove (s_fooEventKey, value);} // 2e. define the protected, virtual On method for this event. protected virtual void OnFoo (FooEventArgs e) {m_eventSet.Raise (s_fooEventKey, this, e);} // 2f. define the method that translates input to this event. public void SimulateFoo () {OnFoo (new FooEventArgs () ;}# endregion # region Code to support the Bar event // 3. define the members necessary for the Bar event. // 3a. construct a static, read-only object to identify this event. // Each object has its own hash code for looking up this // event's delegate linked list in the object's collection. protected static readonly EventKey s_barEventKey = new EventKey (); // 3d. define the event's accessor methods that add/remove the // delegate from the collection. public event EventHandler <BarEventArgs> Bar {add {m_eventSet.Add (s_barEventKey, value);} remove {m_eventSet.Remove (s_barEventKey, value);} // 3e. define the protected, virtual On method for this event. protected virtual void OnBar (BarEventArgs e) {m_eventSet.Raise (s_barEventKey, this, e);} // 3f. define the method that translates input to this event. public void SimulateBar () {OnBar (new BarEventArgs () ;}# endregion}View Code


Action and Func are essentially the same, but they only contain parameters.

Action only has input parameters, and there are many overloaded versions.

Func has input parameters and output parameters. There are also many overloaded versions.

You can use it to know how to play it. The essence is the same.

If there is something wrong, please point out the shortcomings. Please do not write only one: this class of comment is missing. Thank you for your advice and help!

  


[C Language] Is there a function that can clear keys in the cache?

Fflush (stdin)
Clear standard input Cache

# Include "stdio. h"
Main ()
{
Char a, B;
Scanf ("% c", & );
// Fflush (stdin );
Scanf ("% c", & B );
Printf ("\ n % c", a, B );
}

You can try it. If there is no fflush (stdin), if you enter a string of characters "abcd", a = 'A', B = 'B'
If fflush (stdin) exists, after entering "abcd", the program continues to wait for the input, and then enters "efdfsd". The result is a = 'A', B = 'E'

Help [C Language] insert and sort directly

It has been tested and feasible.

# Include "stdio. h"
# Define MAXSIZE 20 // maximum length of a small sequence table used as an Example
Int Insertsort (int r [], int n)
{// Sort by direct insert
Int I, j;
For (I = 2; I <= n; I ++)
{R [0] = r [I]; // r [0] is used as a sentry unit.
J = I-1;
While (r [0] <r [j])
{R [j + 1] = r [j]; // record move-back
J --;
} // While
R [j + 1] = r [0]; // insert to the correct position
For (j = 1; j <= n; j ++) // output the result of each sort.
{
Printf ("% d", r [j]);
} //
Printf ("\ n ");
} //
} // Insertsort

Int main ()
{
Int n, I; // Number of keywords to be sorted
Int r [MAXSIZE];
Scanf ("% d", & n );
For (I = 1; I <= n; I ++) // enter the keyword to be sorted.
Scanf ("% d", & r [I]);
Insertsort (r, n );
}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.