6.1 various types of members
In a type, zero or more members of the following types can be defined:
1)
ConstantA constant indicates that the data value remains unchanged. These symbols are generally used to make the code easier to read and maintain. Constants are usually associated with types instead of instances of types. Logically, constants are always static members. 2)
FieldField indicates a read-only or read/write data value. The field can be static and part of the type status; the field can also be instance (non-static), and the field is part of the object status. We strongly recommend that you declare a field as a private field to prevent the type or object status from being damaged by external code. 3)
Instance ConstructorThe instance constructor is a special method to initialize the instance field of the new object to a good initialization state (that is, to complete the expected initialization. 4)
Type constructorThe Type constructor is a special method for initializing static fields of the type to a good initialization state (that is, completing the expected initialization. 5)
MethodA method is a special function used to change or query the status of a type or status. It acts on the type and becomes a static method. It acts on the object and is called an instance method. The read/write operation is generally performed on fields of the type or object. 6)
Operator overloadOperator Overloading is actually a method that defines how to operate a specific operator on an object. Since not all programming languages Support Operator overloading, Operator Overloading methods are not part of the "common language specification" (CLS. 7)
Conversion OperatorA Conversion operator is a method that defines how to display or implicitly convert an object from one type to another. Not all programming languages Support Operator overloading, so the operator overloading method is not part of the "common language specification" (CLS. 8)
AttributeWith properties (propety), you can use a simple, field-style syntax to set or query the logical state of a type or object, and ensure that the state is not damaged. Static attributes act on types, and instance attributes act on objects. Attributes can be non-parameter (common), but can also have parameters (rare, but common for collection classes ). 9)
EventWith static events, a type can send notifications to one or more static or instance methods. With instance events, an object can send notifications to one or more static or instance methods. If the type of the provided event or the status of the object changes, the event is usually triggered. An event contains two methods, which allow static or instance method registration or cancellation of attention to this event. In addition to these two methods, an event usually uses a delegate field to maintain the registered method set. 10)
TypeYou can define other types nested in it. This method is usually used to break down large and complex types into smaller building units to simplify implementation. No matter what programming language is used, its compiler must be able to process your source code and generate metadata and IL code for each of the above members. No matter which programming language is used, the metadata format is completely consistent. So that the CLR can become "RunTime in public languages ". Metadata is the public information generated and used by all languages. CLR uses the public metadata format to determine the behavior of constants, fields, constructors, and other Members at runtime. In short, metadata is the relationship between the entire. NET Framework Development Platform, which enables seamless integration of programming languages, types, and objects.
6.2 type visibility
When defining a type in a file range, you can specify the visibility of the type as public or internal.
The public type is not only visible to all the code in the Assembly it defines, but also to the Code in other assembly. The internal type is visible only to all the code in the defined assembly and not to the Code in other assembly. When defining a type, if the visibility of the type is not explicitly defined, the C # compiler sets the visibility of the type to internal by default. CLR and C # Allow one assembly to perform public operations on the other assembly with internal visibility through friend assembly. When building an assembly, you can use the System. Runtime. CompilerServices namespace to define an attribute named InternalsVisibleTo to indicate other assemblies that it considers as "friends. This attribute is used to obtain a string parameter that identifies the name and public key of a user-defined assembly.
using Systemlusing System.Runtime.CompilerServices [assembly:InternalsVisibleTo("Winterllect,publickKey=12345678....asdf")].....
The "youyuan assembly" function is only applicable to the Assembly with the same release time, preferably packaged and released together. Due to the high degree of mutual dependency between user-dependent assembly, version incompatibility may occur if versions are staggered for too long. 6.3 member accessibility
When defining a member of a type (including a nested type), you can specify the accessibility of the member ).
Comparison of the accessibility of members in CLR and C:
CLR terminology |
C # terminology |
Description |
Private |
Private |
Members can only be accessed by methods of the definition type or any nested type. |
Family |
Protected |
Access is limited to include classes or types derived from include classes |
Family and Assembly |
Not Supported |
Members can only be accessed by methods of the defined type, any nested type, or any derived type defined in the same set of programs. |
Assembly |
Internal |
Access is limited to the current Assembly only |
Family or Assembly |
Protected internal |
Access is limited to the current Assembly or type derived from the include class |
Public |
Public |
Unrestricted access |
If the accessibility of declared members is not displayed in C #, the compiler usually selects private by default. CLR requires that all Oh members of the interface type have public access. Therefore, C # prohibits developers from displaying the accessibility of the specified interface. When a derived class overrides a member defined in its base class, the C # compiler requires that the original and override members have the same access. But the CLR does not. When derived from a base class, the CLR allows you to relax the accessible limitations of members, but cannot tighten them. The CLR promises that a derived class can always be converted to a base class and get access control over the base class methods.
6.4 static class
In C #, use the static keyword to define classes that cannot be instantiated. This keyword can only be applied to classes and cannot be referenced in structures (value types ). This is because CLR always allows Value Type instantiation.
C # The Compiler imposes the following limitations on static classes: 1) Static classes must be derived directly from the base class System. Object. It is meaningless to derive from any other base classes. Inheritance only applies to objects, but you cannot create static class instances. 2) The static class cannot implement any interface, because only the instance of the class can call the interface method. 3) a static class can only define static members (fields, methods, attributes, and events). Any instance Member will cause the compiler to report an error. 4) Static classes cannot be used as fields, method parameters, or local variables, because they all represent variables that reference an instance. Defining a class using the static keyword causes the C # compiler to mark the class as abstract (not instantiated) and sealed (not derived) at the same time ). The compiler will no longer generate an instance Constructor (. ctor) in the type ).
6.5 branch classes, structures, and interfaces
The keyword partial tells C # compiler that the source code of a class, structure, or interface definition may be dispersed into one or more source code files.
There are three main reasons for us to distribute a type of source code to multiple files: 1) Use the partinal keyword in source code control and distribute the type of code to multiple source code files, each file can be checked out separately so that multiple developers can edit this type at the same time. 2) In the same file, a class or structure is divided into different logical units 3) code splitting 6.6 components, polymorphism and version control components Software programming (CSP) it is the success of OOP to the extreme. The following lists some features of components. 1) component (. (2) The component has its own identifier (name, version, language and culture, and public key). (3) the component always maintains its own identifier (the code in the Assembly will never be statically linked to another assembly :. NET always uses dynamic links) 4) The component clearly specifies the component it depends on (reference metadata table ). 5) The component must document its classes and members. 6) The component must specify the required security permissions. 7) The component must publish an interface (object) that will not be changed in any "maintenance version ). "Maintain version" (servicing version) indicates the new version of the component, which is backward compatible with the original version of the component. Generally, "maintenance version" includes bug fixes, security patches, or some minor function enhancements. However, in "maintenance version", no new dependencies or additional security permissions are required. A large part of CSP involves version control. Components change over time and are released according to different timelines. In. NET, the version number includes four parts: the main version number (mahor version), the minor version number (minor version), the internal version number (build number), and the revision number (Reissue ). The major/minor section usually represents a continuous and stable feature set of the Assembly, while the build/revision section usually represents a maintenance of this function. When a type defined in a component (assembly) is used as a base class of a type in another component (assembly), a version control problem occurs. C # provides five keywords that can affect the version control of components. You can associate them with the application type and/or type members.
C # keywords |
Type |
Method/attribute/event |
Constant/Field |
Abstract |
Indicates that the instance of this type cannot be constructed. |
Indicates that in order to construct an instance of the derived type, the derived type must be overwritten and this member is implemented. |
Not Allowed |
Virtual |
Not Allowed |
Indicates that this member can be rewritten by a derived class. |
Not Allowed |
Override |
Not Allowed |
Indicates that the derived type overrides the member of the base type. |
Not Allowed |
Sealed |
Indicates that this type cannot be used as a base class. |
Indicates that this member cannot be overwritten by a derived type. You can only apply this keyword to methods that are preparing to override a virtual method. |
Not Allowed |
New |
When referenced by a nested type, method, attribute, time, constant, or field, it indicates that the member has no relationship with similar members in the base type. |
How does CLR call virtual methods, attributes, and events? The following Employee class defines three different methods:
Internal class Employee {// non-virtual instance method public int32 GetYearsEmployed (){...} // virtual method public virtual String GenProgressReport (){...} // static method public static Employee Lookup (String name ){...}}
The compiler compiles the above Code and writes three record items in the method definition table of the generated assembly. Each record item uses a set of identifiers (flag) to specify whether the method is an instance violation, a virtual method, or a static method.
CLR provides two method call commands: 1) call the call command can call static methods, instance methods, and virtual methods. When calling a static method using the call command, you must specify the type of the method to be called by CLR. When calling an instance method or virtual method using the call command, you must specify the variable that references an object. The call command assumes that the variable is not null. In other words, the type of the variable indicates the type of the method to be called by CLR. If the variable type does not define this method, check the base type to find the matching method. Call commands are often used to call a virtual method in non-virtual mode. 2) The call command callvirt can call the instance method and virtual method, but cannot call static methods. When calling an instance method or virtual method using the callvirt command, you must specify the variable that references an object. When callvirt is used to specify a method to call a non-real-world sample method, the variable type specifies the type of the method that is ultimately called by CLR. When calling the real-world sample method using the callvirt command, CLR will investigate the actual type of the object to be called and then call the method in a multi-state mode. To determine the type, the variable used to send the call must not be null. In other words, during compilation, the JIT compiler generates code to verify whether the variable value is null. It is precisely because of this additional check that the invocation speed of all callvirt commands is slightly slower than that of call commands. Note that even if the callvirt command calls a non-virtual instance method, this null check will be executed. C # Use the callvirt command to call all instance methods. When the compiler calls a method defined by a value type, it tends to use the call command because it is sealed. This means that even if you have to write some virtual methods in the value type, you do not need to consider the problem of polymorphism. Whether it is call or callvirt to call the instance method or virtual method, these methods usually accept a hidden this real parameter as the first parameter of the method. This real parameter references the object to be operated. When designing a type, minimize the number of defined virtual methods. First, calling a virtual method is slower than calling a non-virtual method. Secondly, the JIT compiler cannot embed virtual methods, which further affects performance. Third, virtual methods make Version Control of components more vulnerable. Fourth, when defining a base type, you often need to provide a set of simple methods for overloading. If you want these methods to be polymorphism, it is best to call the most complex method virtual method, so that all simple methods with heavy loads become non-virtual methods. For example:
Public class Set {Int32 private m_length = 0; // The Simple Method of this overload is non-virtual public Int32 Find (Object value) {return Find (value, 0, m_length );} // The Simple Method for this overload is non-virtual public Int32 Find (Object value, Int32 startIndex) {return Find (value, startIndexx, m_length-startIndex );} // The most versatile method is the virtual method. public virtual Int32 Find (Object value, Int32 startIndex, Int32 endIndex) can be rewritten) {// here is the rewrite implementation ....} // other methods}
Rational use of the visibility of types and the accessibility of members
First, when defining a new type, the compiler should be a sealed class by default so that it cannot be used as a base class. C # the compiler is not a sealed class by default, but allows developers to use the keyword sealed to mark the class as a sealed. The use of sealing is better than that of non-sealing, for the following reasons: 1) version control can easily change the sealing class to non-sealing class, but changing the non-sealing class to the sealing class will cause a lot of trouble. 2) performance as mentioned above, the nature of calling virtual methods is far inferior to that of calling non-virtual methods, because CLR defines the method to be called to determine which type, you must find the object type at runtime. However, if the JIT compiler sees that the virtual method is called using the sealed type, the virtual method can be called using a non-virtual method. 3) the security and predictability class must protect its own State and cannot destroy itself. When the class is not sealed and non-private, the derived class can access and change the base class status. Defining a class follows some principles: 1) when defining a class, unless you are sure to use a class as the base class and allow the derived class to perform special processing on it, otherwise, it is always explicitly specified as the sealed class. In addition, classes are designated as internal classes by default, unless you want to expose this class outside the assembly. 2) define the data field as private within the class. 3) define your methods, attributes, and events as private and non-virtual within the class. Of course, a method, attribute, and event are defined as public to expose some functions of the class. Virtual is the final consideration, Because virtual members will give up a lot of control, lose independence, and become completely dependent on the correct behavior of the derived class.