Document directory
- I. Application scenarios
- Ii. Members and accessibility
- Iii. generics and interfaces
- Iv. Actual examples of classes and structures
Structures and classes all share the same abstract data type, including data and data operations. The difference is that the structure focuses on data semantics, while the class focuses on behavior semantics. We don't care about how the object is implemented internally. We care about what interfaces and operations it provides to me. Technically, the structure belongs to the value type, and the class belongs to the reference type. The structure cannot specify the inheritance base class type. The class can. However, both structures and classes can implement interfaces.
I. Application scenarios
Structure application scenarios:
1. Custom Data Types. Data members are public and provide tool functions.
2. abstract data types. Data members are sealed and provide relevant data operation functions.
In short, it is all about data.
Application scenarios:
1. Provide a group of classes to form an organic whole and form a system. The class data members are sealed and only provide function interfaces for mutual communication.
A class consists of different classes to form a system for inter-class communication. The class itself is part of the entire system.
Ii. Members and accessibility
As a tool for abstract data types, classes and structures provide rich encapsulation functions.
1. Field definition data member, no Encapsulation
2. Access methods of attribute encapsulation Fields
3. functions provide available operations
4. The event provides a message processing model.
5. The indexer encapsulates the data set.
In addition
Constructor and destructor are responsible for initializing and clearing garbage (IDispose mode is required in c)
For members, there can be three categories: 1. Class Members, shared by all instances; (static modifier) 2. public object members; (public modifier) 3. Private object members.Public members are the most importantPrivate Members are internal implementation details.
Public members are the characteristics of objects, because users can only interact with objects through public members. You can extract public members to form an independent interface to isolate specific implementations. In this way, designers can provide different class implementations to customers.
Iii. generics and interfaces
Classes and structures all belong to implementations, while interfaces are standards. The client should avoid direct access to specific implementations. Otherwise, the client needs to change according to implementation changes, which is obviously economic. However, there are differences between classes and structures, and classes focus on behavior, so they are more matched with interfaces; while structures focus on data, while interfaces do not have data, and interfaces belong to reference types, when the structure is converted into an interface as a value type, it will produce packing and performance problems. Therefore, interfaces are generally not used in combination with structures, and the structure should be a simpler data unit and should not add too much functionality. If you need to design components with rich functions, it is best to implement them based on classes. When a structure acts as a data unit, there is little room for modification and design, because the application scenarios of the Data Unit are mostly modified by others and there is not much autonomy. The conclusion is that the structure itself can be used as a standard.
Generics are unfinished types, so they provide the opportunity to customize client types. Every instance of the generic type shares the same or similar code. Why does the client need the generic type?
C # is a strongly typed system. Even if the logic is the same, different types make different code in the compiler. When the client needs to adopt the same logic for different types, generics provide a fast channel that is beyond the strong type restrictions. For example, an int + int and float + float are almost the same in our human opinion. However, a strong compiler requires you to repeat the code and the generic compiler can achieve T + T, then let the client generate any type with parameters that support + operations.
From the client perspective, it does not care about implementation, but what interfaces are. The significance of generics for the client is to strengthen the interface, from providing a specific type of interface to providing a new type of interface that meets a certain range of conditions. This greatly enhances availability. (According to the actual application, we should regard generic as normal, and a single type of interface is a special State ).
Iv. Actual examples of classes and structures
This section is complementary. This section uses code to illustrate the problem.
1. Typical classes
Imagine a two-element operation,? B = c, where? Unknown, but knows when to execute the operation.
Class A {int a, B, c; // internal data public class abArgs: EventArgs {public int A {set; get;} public int B {set; get ;} public abArgs (int a, int B) {A = a; B = B ;}}// the parameter type of the event is public event EventHandler <abArgs> calcEvent; // event public delegate int calcType (int x, int y); // delegate type of the algorithm calcType calcFunc; // internal data public calcType CalcFunc {set {calcFunc = value ;}} // algorithm delegate public int X {set {a = value; calc ( ) ;}// A public int Y {set {B = value; calc () ;}// B void OnCalc () {if (calcEvent! = Null) calcEvent (this, new abArgs (a, B);} // internal event triggering public int Result {get {return c ;}} // c public class CalcException: Exception {public CalcException (string mess): base (mess) {}} // Exception type // void calc () {if (calcFunc! = Null) c = calcFunc (a, B); else throw new CalcException ("no operation function is specified. "); OnCalc ();}}
Class A provides AB settings and Result c is obtained. However, class A does not know the algorithm, so it must be provided externally. A will trigger the computing event calcEvent. Objects interested in this event can listen on this event. Class A is not perfectly designed. It immediately calls the operation process when AB changes, rather than giving the execution time to the customer. Generally, it is reasonable to calculate it only after we prepare AB. According to the features of A's design, I designed an exception type. This exception occurs when the algorithm delegate is not ready.
The following is how to extract the interface:
interface IA { event EventHandler<A.abArgs> calcEvent; A.calcType CalcFunc { set; } int X { set; } int Y { set; } int Result { get; } }
The obvious disadvantage is that A nested type in the interior. Suppose we have designed class B based on the interface, but there is A. abArgs in it, which is embarrassing. Through the extraction interface, the Code becomes intuitive and convenient for the client. On the other hand, we can implement new types.
Here is the re-designed A2, which puts the operation in the process of obtaining the result:
Class A2: IA {EventHandler <. abArgs> mcalcEvent; event EventHandler <. abArgs> IA. calcEvent {add {mcalcEvent + = value ;}remove {mcalcEvent-= value ;}}. calcType mCalcFunc;. calcType IA. calcFunc {set {mCalcFunc = value ;}} int mX; int IA. X {set {mX = value; Modify = true ;}} int mY; int IA. Y {set {mY = value; Modify = true ;}} bool Modify = false; int mResult; int IA. result {get {if (! Modify) return mResult; if (mCalcFunc = null) throw new A. CalcException ("no operation function is specified. "); MResult = mCalcFunc (mX, mY); Modify = false; if (mcalcEvent! = Null) mcalcEvent (this, new A. abArgs (mX, mY); return mResult ;}}}
A2 uses the interface IA and is "explicitly implemented ". A2 is a fully closed implementation. It has no public members and can only be accessed through interfaces. For customers using IA, they can accept the new A2 without any pain and get a little performance improvement (reducing the number of computations ).
2. Initialization and Termination
3. Copy