Questions about C ++ switching to C #: A Preliminary Study on Inter-class communication methods in C #

Source: Internet
Author: User

From http://blog.csdn.net/zhuweisky/article/details/415756

In C #, there are no free functions and no free variables. Everything must be encapsulated in the class. In C ++, using global variables for inter-function communication and inter-class communication are common methods. However, this becomes impossible in C, this indeed makes C ++ programmers worried. C # Of course, it has a good reason not to support free functions and free variables, because "freedom" implies factors that affect program robustness and maintainability, such as conflicts and insecurity. Of course, there are many technologies that can solve the problem of inter-class communication in C #. This article introduces several of them.


I. Main class involved in the problem domain

Before the introduction, let's make a description. Generally, we can encapsulate the relevant data elements required for Inter-class communication into a structure, which is called the "communication structure" and mark itInformation structIt is a pure C structure, that is, nothing except public data members. When messages need to be exchanged between classes, a "communication structure" instance can be generated and then transmitted between classes. In addition, I call the information-providing class provider.
Class (hereinafter referred to as provider), the class that receives information is called Master Class (hereinafter referred to as master ). Of course, the two Communication classes can be provider and master. Please note that the provider will appear later
Objects and master objects, which correspond to the provider and master instances.

The master can obtain the required information from the provider in two ways: Forward retrieval and reverse retrieval. Each method has several different implementation methods. I will introduce them one by one.

Ii. Get information positively

The so-called "Forward" gets information, that is, according to the general straight line thinking method, the master needs to obtain information from the provider, and directly let the master access a member of the provider. In this way, the master is active because it always takes the initiative to visit the provider, while the provider is relatively passive.

As expected, there are mainly the following methods.

1.Provider Expose a member variable or attribute

The master can access this member variable or attribute to obtain the required data. This method is convenient for obtaining some simple non-confidential information. Generally, this information can be provided directly by the provider itself and is not easy to change, such as obtaining a control (of course a provider ).
Object) size or color. The disadvantage of this method is that if the data provided by the provider is confidential, this security cannot be guaranteed.

2.Provider Expose a method

If the required information is complex (for example, it can be obtained through simple computation), or is often changing, providing such information through one method is undoubtedly a better choice. There are two implementation methods:

(1) return values

This is often used. In this case, the master can communicate with the provider through parameters. For example:

Public Information getinformation (parameter );

(2) Pass the ref or out Parameter

If the return value of a method is used for other purposes, such as determining whether the method is successfully executed, you can use ref or out to "Remove" the required information from the method ". For example:

public int GetInformation(out Information info) ;

You may have seen that the main problem with the way to get information is that the master does not know when the provider will prepare the required data, that is, does the master visit the provider at an appropriate time? If the time is incorrect, the correct information is obviously not obtained.

To solve this problem, we can reverse obtain information.


Iii. Reverse Information Retrieval

After the provider prepares the data,ActiveProvide the data to the master. Compared with the way to obtain information, we can see that the master-customer relationship has changed, and now the provider takes the initiative to visit the master. This naturally solves the problem that the timing of positive information retrieval may be immature.

In practice, the most commonly used method is to obtain information in reverse order. Generally, when the master needs data, it creates a provider object, after the provider object obtains the data and performs relevant processing, it stores the required information in an information
Object, and then submit the information object to the Master. Since the end of the life cycle of the provider object, the master can process the data. To give readers an intuitive understanding, let's give a simple example:

 

This is a simple Library Information Management System. Figure 1 shows the master object interface, and Figure 2 shows the provider.
Object interface. When you click the "add" button in figure 1, the page shown in Figure 2 is displayed. After you complete the information, click "Submit ", you can add a new book to the management system.

The information structure can be designed as follows:

public struct Information    {       public string book_name ;       public string author ;       public string date ;}

1. Data Communication through static member variables of the class

This is the simplest way to directly simulate the communication using global variables in C ++. We take an information object as the static member variable of the master and set its modifier to public. Then, the provider
After the provider write operation is complete, the master can process static information objects. Now the problem arises-how does the master know that the provider has completed the write operation? Callback Function !!! -This is the first response of C ++ programmers. Can it be in C? Yes, but C # provides a safe function pointer called a delegate. We have already pointed out that the provider object is generally created by the master object, so the master object can be passed to the provider object as a delegate instance when creating the provider object, after the provider completes the write operation, the callback can be completed through the delegated instance.


Next let's take a look at the main C # pseudo code of this method.

First, define the delegate:

public delegate void D_Callback() ;

Let's look at the master class again:

Class master {public static information object_ I; Public void getinformation () {d_callback callback = new d_callback (processinformation); provider object_p = new provider (callback );...... // For example, display the object_p interface} private void processinformation (){...... // process object_ I }......}

Next let's take a look at how providers are implemented:

Class provider {private d_callback back; public provider (d_callback yourback) // The constructor must use the "callback function" as the parameter {This. back = yourback;} // if you click the "Submit" button in Figure 2, the following processing function private void button#click (){...... // access the master. object_ I, and write the information back (); // trigger the callback function call, that is, call the processinformation function in the master this. close (); // The provider object completes the task and can be recycled by GC. }}

It's easy, isn't it? Yes, it is simple enough. It is only the C # version that uses global variables for communication in C ++. But is this a good method? Not good. This method only completes the task, but it is not doing well. Even, this implementation is very ugly. There are at least two reasons:

First, it is very inappropriate to make the information object the public static object of the master, because it is not only the provider class but also all other classes (including malicious classes) you can write information to this static region, thus losing security.

Second, the master needs to package its member functions (as Callback functions) into delegates and pass them to the provider class as the constructor parameter, which leads to very tight coupling between the master class and the provider class, just like a consortium baby. If we want to reuse only one of these classes without bringing another class, it is totally impossible, which violates the basic principle of Ood.

Bad, isn't it ?! Let's look at an improved version.

 

2. Data Communication through stack object Replication

In the provider object, the obtained data is stored in its own private information object, and then the information object is used to call the delegate passed from the constructor. In this way, when you jump to the callback function of the master, because information is struct, and struct is a value type, the information object will be copied on the stack, and its copy will be accessible by the callback function. In this way, the information is transmitted from the povider to the master.


Let's take a look at the code changes:

Public Delegate void d_callback (Information object_ I); // here the information object is used as the callback function parameter class master {// no longer has a static information member public void getinformation () {d_callback callback = new d_callback (processinformation); provider object_p = new provider (callback );......} private void processinformation (Information object_ I)
{... // Process a copy of object_ I }......}

Next let's take a look at the change of provider:

Class provider {private d_callback back; // Add a private information member to store the private information object_ I; public provider (d_callback yourback) {This. back = yourback;} private void button#click (){...... // write the information to this. object_ I // call the processinformation function back (this. object_ I); this. close ();}}

This method avoids exposing a public static member by copying stack objects ),

Security is enhanced, but the tight coupling between the master and provider is not diminished. Is there no perfect solution? Yes! That is, through the event publishing-booking method, the event publishing class does not have to know any situations of the class of the scheduled event, thus, the previous circular dependency between the master and provider is converted to one-way dependency (only the master depends on the provider), which effectively reduces the coupling between the master and provider.

3. Communication through the event mechanism

The event mechanism provides an elegant, efficient, and flexible solution for inter-class communication.

We only need to declare and release the event in the provider class, and trigger the event when appropriate. Then, we can reserve the event in the master class and define the event processing function. In this way, the provider class can be used not only for the master class, but also for other classes that need the same information. In this case, the master class is only a client of the provider class.


See how it is implemented.

First, if a delegated instance is to become an event, the delegated prototype Declaration must be in the following format:

public delegate void D_Callback (object sender ,MyEventArgs e) ;

Note that myeventargs must be inherited from the eventargs class, which is used to wrap the information to be passed. Here we can simply implement the following:

public class MyEventArgs:System.EventArgs    {       public Information object_I;}

Next, let's take a look at how the provider publishes an event and triggers the event:

Class provider {public event d_callback putoutinformation; // publish event private void button1_click () {myeventargs ARGs = new myeventargs ();...... // write information to args. object_ I putoutinformation (this, argS); // triggers the event this. close ();}}

Is it simple, clear, and clear ?! The provider does not need to know the existence of the master class.

Let's take a look at how the master class schedules events and how to obtain the required information when an event occurs.

Class master {public void getinformation () {privoder object_p = new privoder (); // scheduled event object_p. putoutinformation + = new d_callback (this. processinformation );.....} private void processinformation (Object sender, myeventargs e ){..... // PROCESS e. object_ I}
    ......}  

The above code is simple and clear, so I don't have to worry about it any more.

C # is a fully object-oriented language. Compared with C ++, C # removes global variables and global functions, and introduces common features of object-oriented programming such as events and attributes. Because global variables are not available, you must find another solution in C # To solve inter-class communication problems, the event mechanism provided by C # is just a good solution to such problems. Although C # can also simulate C ++ to complete communication through static storage zone or stack replication, however, these methods give people the feeling that they are clumsy and not elegant. Therefore, when you cannot find a better way to implement inter-class communication, use the event mechanism.

 

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.