CLR via C # Learning notes----General summary of Knowledge

Source: Internet
Author: User
Tags comparable

1th. CLR Execution model

The various components of a managed module: PE32 or pe32+ header, CLR header, metadata, IL (intermediate language) code.

High-level languages typically expose only a subset of all the functionality of the CLR. However, IL Assembly language allows developers to access all the functionality of the CLR.

The Jitcompiler function compiles the IL code for a method to compile the cost of the CPU instruction. Since IL is compiled in "instant" (just in time), this component of the CLR is often referred to as the jitter or JIT compiler.

Microsoft defines a common language specification (Common Language specification, CLS) that defines a minimum set of features that all languages must support.

2nd. Build, package, deploy, and manage applications and types

A response (response file) is a text file that contains a set of compiler command-line switches.

In addition to the files explicitly specified on the command line, the compiler automatically finds two files named csc.rsp (local and global).

A setting in the local and global response file conflicts, whichever is set on the local file. Similarly, the settings explicitly specified on the command line overwrite the settings in the local response file.

To add interest, select View | in ILDASM Statistics ", the interesting information is displayed.

AssemblyVersion This version number is very important, it uniquely identifies an assembly. An assembly is tightly bound to a specific version of the referenced assembly.

3rd. Sharing assemblies and strong-Named assemblies

Obviously, it is not enough to differentiate an assembly by file name alone. The CLR must provide a mechanism for uniquely identifying an assembly. This is the origin of the strong-named assembly. A strong-named assembly has 4 important attributes, which collectively uniquely identify the assembly: a file name (excluding the extension), a version number, a language cultural (culture) identity, and a public key.

Because the public key is a very large number, a small hash value derived from the public key is often used. This hash value is called Public Key Token(Public key token).

The CLR will never use a public key token when making a security or trust decision because several public keys may get the same public key token after hashing.

If an assembly is to be accessed by multiple applications, it must be placed in a known directory, and the CLR must know to automatically check the directory when it detects a reference to the assembly. This known location is known as the Global Assembly Cache (Assembly cache, GAC).

When you install a strong named assembly to the GAC, a check is performed to verify that the file containing the manifest has not been tampered with. This check is performed only once at installation time. Conversely, when a strong-named assembly is loaded from a directory other than the GAC, the CLR verifies the assembly's manifest file, verifying that the contents of the file have not been tampered with, resulting in additional performance overhead for each load of the file.

4th Chapter Type Foundation

The IS operator, as operator, never throws an exception.

The IS operator uses the following:

If (O is Employee)
{
Employee E = (employee) O;
}

The CLR actually checks the type of two objects, which undoubtedly has a certain effect on performance. C # specifically provides the AS operator to simplify the way this code is written, while improving its performance.

Employee E = o as Employee;
if (E! = null) {}

If O is incompatible with the employee type, the AS operator returns NULL, which causes the CLR to verify the type of the object once. The IF statement simply checks if E is null, which is much faster than verifying the type of the object.

The C # compiler provides a feature called an external alias (extern alias) that addresses this rare but still possible problem: programming to differentiate different assemblies rather than just distinguishing between different namespaces. External aliases also allow access to a type from two (or more) different versions of the same assembly. For more information about external aliases, see the C # Language specification.

In addition to globally turning overflow checking on or off, programmers can control overflow checking in specific areas of the code. C # achieves this flexibility by providing checked and unchecked operators.

5th. Primitive types, reference types, and value types

If you define a type that overrides the Equals method, you should also override the GetHashCode method to ensure that the equality algorithm and the object hash code algorithm are consistent. This is because in the implementation of the System.Collections.Hashtable type, the System.Collections.Generic.Dictionary type, and some other collections, two objects must have the same hash code in order to be equal.

Do not confuse dynamic and var. Declaring a local variable with var is simply a simplified syntax that requires the compiler to infer a specific data type based on an expression. The var keyword can only be used to declare local variables inside a method, while the dynamic keyword can be applied to local variables, fields, and parameters. An expression cannot be converted to var, but can be transformed into dynamic. You must explicitly initialize a variable declared with var , but you do not need to initialize a variable declared with dynamic .

When code invokes a member using the dynamic expression/variable, the compiler generates special IL code to describe the desired operation. This special code is called Payload (payload).

Although it is possible to simplify the syntax with dynamic features, it depends on whether it is worthwhile. After all, loading all of these assemblies and additional memory consumption can have an additional impact on performance.

6th. Type and member basis

When building an assembly, you can use a attribute named InternalsVisibleTo defined in the System.Runtime.CompilerServices namespace to indicate that it is considered " Other assemblies for the friend element.

When designing a type, you should minimize the number of virtual methods that are defined. First, calling a virtual method is slower than calling a non-virtual method. Second, the JIT compiler cannot embed (inline) virtual methods, which further affects performance. Third, virtual methods make versioning of components more vulnerable. IV, when defining a base type, it is often necessary to provide a set of easy methods for overloading (convenience method). If you want these methods to be polymorphic, the best approach is to make the most complex methods virtual, making all the easy methods of overloading a non-virtual method.

8th Chapter Method
Do not call any virtual methods in the constructor that affect the constructed object. The reason is that if the virtual method is overridden in a derived type of the type that is currently being instantiated, the overridden implementation is called. However, in an inheritance hierarchy, the fields are not fully initialized. Therefore, calling a virtual method will result in unpredictable behavior.

about the performance of a type constructor: For static fields that have inline initialization (the type definition table of the class is generated with an added beforefieldinitMetadata tagged record entry), as long as it is initialized before access, it doesn't matter what time it is. An explicit type constructor may contain code that has side effects, so you need to run the exact time.

The extension method has potential versioning problems. If Microsoft were to add a IndexOf instance method for their StringBuilder class in the future, and just like the prototype my code tried to invoke, when I recompile my Code, The compiler binds to Microsoft's IndexOf instance method. In this way, my program will behave differently. This versioning issue is another reason to be cautious when using extension methods.

With regard to the partial approach, there are some additional rules and principles to keep in mind:

    • They can only be declared in partial classes or structs.
    • The return type of a partial method is always void, and any parameter cannot be marked with an out modifier. A partial method can have a ref parameter, which can be a generic method, an instance or a static method, and can be marked as unsafe.
    • If both are applied to custom attribute, then attribute will be merged together.
    • Partial methods are always treated as private methods.

9th Chapter Parameters

Note that changing the default value of a parameter is potentially dangerous if the method is called from outside the module. Call site embeds the default value in its invocation. If you later change the default value of the parameter, but do not recompile the code that contains the call site, it will pass the old default value when calling your method. Consider using the default value 0/null as the Sentinel value:

Do not do this:
private static string Makepath (String filename = "Untitled") {
return String.Format (@ "c:\{0}.txt", filename);
}

But to do this:
private static string Makepath (string filename = null) {
return String.Format (@ "c:\{0}.txt", filename?? "Untitled");
}

The empty join operator (??) is used here.

For a variable passed to a method in a quoted way, its type must be the same as the type declared in the method signature, because it guarantees type safety.

guidelines for parameters and return types : When declaring the parameter types of a method, you should specify the weakest type as much as possible, preferably an interface rather than a base class (I understand it as the base type). For example, if you are writing a method to handle a set of data items, it is best to use an interface (such as ienumerable<t>) to declare the parameters of the method instead of a strong data type (such as list<t> ) or a stronger interface type (such as icollection<t> or ilist<t>).

10th Chapter Properties

Anonymous type

With the anonymous type feature of C #, you can use very concise syntax to declare an immutable (immutable) tuple type (tuple). A tuple type is a type that contains a set of properties that are usually associated in some way.

var O1 = new {Name = "Jeff", year = 1964};

This line of code creates an anonymous type, and I don't specify the type name after the new keyword, so the compiler automatically creates a type name for me and doesn't tell me what the name is exactly.

The compiler is very "considerate" when it comes to defining anonymous types. If it sees that you have more than one anonymous type defined in the source code, and those types have the same structure, it will only create an anonymous type definition, but create multiple instances of that type. The so-called "same structure" means that in these anonymous types, each property has the same type and name, and these properties are specified in the same order. This checks to see if two objects contain equal values and assigns a reference to one object to the variable that is pointing to another object. You can also create an implicitly-typed array:

var people = new[] {
O1,//o1 See previous section
New {Name = "Kristin", year = 1970},
New {Name = "Aidan", year = 2003},
New {Name = "Grant", year = 2008}
};

An instance of an anonymous type cannot be leaked to the outside of a method. If you want to pass a tuple, you should consider the system.tuple type.

Similar to anonymous types, once a good one Tupleis created, it is immutable (all properties are read-only).

Of course, it is very important that the producer of aTuple (the person who writes it) and the consumer (who uses it) must #属性返回的内容有一个清楚的理解 to the Item. For anonymous types, the actual name of the property is determined by the source code that defines the anonymous type. For Tuple types, properties are all called Item# by Microsoft and we cannot make any changes to this.

Chapter 11th Events

If you define an event member, it means that the type provides the following capabilities.

    • method to register its interest in the event.
    • method to unregister its attention on the event.
    • When this event occurs, the registered method receives a notification.

The section on designing the types of events to expose is written in detail, with thread safety in mind, and book p228-233 suggests repeated reading.

13th Chapter Interface

An important feature of interface inheritance is that an instance of a type that implements an interface can be used wherever an instance of the interface type of the appliance name is made available.

At run time, a variable can be transformed from one interface type to another, as long as the object's type implements both interfaces.

String s = "Jeffrey";
IComparable comparable = s;
IEnumerable enumerable = (IEnumerable) comparable;

When you define a display interface method in C #, you are not allowed to specify accessibility (such as public or private). However, when the compiler generates metadata for a method, its accessibility is automatically set to private, preventing other code from invoking the interface method directly when using instances of the class. To invoke an interface method, only one variable of the interface type can be used.

Chapter 14th character, String, and text processing

The System.Security.SecureString class can use it to protect sensitive string data, such as passwords and credit card information.

When constructing a SecureString object, it allocates an unmanaged block of memory within it, which contains an array of characters. The reason to use unmanaged memory is to avoid the garbage collector's "snare".

Use a SecureStringto specify the /unsafe switch option for the C # compiler at compile time.

16th Chapter Array

If you just need to copy some elements of the array to another array, you can choose system.buffer 's BlockCopy method, which executes faster than the copy of array Method Fast. However, the BlockCopy method ofBuffer only supports primitive types, and it does not provide the same transformation capabilities as the Copy method of Array .

If you need to reliably copy an array of elements into another array, you should use the System.Array constrainedcopy method. This method guarantees that the copy is done without destroying the data in the destination array, or throws an exception.

Note that thearray.copy method performs a shallow copy. In other words, if the array element is a reference type, the new array will reference the existing object.

If performance is the primary goal, avoid allocating managed array objects on the heap. Instead, the array should be allocated on the thread stack, which is done through the C # stackalloc statement. The stackalloc statement can only create one-dimensional 0 -based arrays of value-type elements, and value types must never contain fields of any reference type.

unsafe {
Const INT32 width = 20;
char* pc = Stackalloc Char[width]; allocating arrays on the stack
...
}

Typically, because an array is a reference type, an array field defined in a struct is actually just a pointer or reference to an array, and the array itself is outside of the structure's memory. However, you can embed the array directly into the structure, as in the Chararray structure in the following code. This is the allocation of arrays on the stack.

Internal unsafe struct Chararray {
This array embeds the structure inline inline (inline) array
Public fixed Char characters[20];
}

18th Chapter Custom Attribute

When a attribute is applied, C # allows a prefix to explicitly specify the target element to which the attribute is to be applied. In some cases, however, a prefix must be specified to clearly indicate our intentions to the compiler.

[Return:someattr]
public int SomeMethod ()
{return somevalue;}

To tell the compiler to customize the scope of the attribute's legal application, an instance of the System.AttributeUsageAttribute class needs to be applied to the attribute class.

One of the properties of AttributeUsageAttribute is inherited, which indicates whether attribute applies to both derived classes and overridden methods when applied to the base class. Note that the. NET framework only considers target elements such as classes, methods, properties, events, fields, method return values, and parameters to be inheritable.

When calling Attribute 's getcustomattribute or getcustomattributes methods, these methods invoke the constructor of the Attribute class internally. And it is possible to invoke the property's set accessor method. This is equivalent to allowing unknown code to run in the AppDomain, so it is a potential security risk.

Using the System.Reflection.CustomAttributeData class, you can suppress the execution of code in the attribute class while looking for attribute.

20th Exception and state management

If you simply use the throw keyword itself to re-throw an exception object, the CLR will not reset the stack's starting point.

In your code, if you determine that the state is damaged to an extent that cannot be repaired, you should destroy all the corrupted state and prevent it from causing more damage. Then, restart the application, initialize the state to a good state, and send the hope that the status is no longer corrupted. At this point, you can call the AppDomain 's Unload method to unload the entire AppDomain.

If you feel that the state is too bad to terminate the entire process, you should call environment 's static FailFast method.

In order to add additional data or context to the exception, you can add data to the database property of the exception object (a collection of key/value pairs) and then re-throw it (only throw).

Runtimehelpers.prepareconstrainedregions is a very special method for constraining the execution region (CER). If the JIT compiler finds that this method was called before a try block, the code in the catch and finally blocks associated with the try is compiled ahead of time. The JIT compiler loads any assembly, creates any type of object, invokes any static constructor, and JIT-compiles any method. If any of these operations cause an exception, the exception occurs before the thread enters the try block.

21st chapter Automatic Memory Management (garbage collection)

Use the System.Runtime.ConstrainedExecution.CriticalFinalizerObject type to ensure finalization. The CLR treats the class and its derived classes in a very special way: 1. Pre-compiling the Finalize method; 2. When a non-criticalfinalizerobject derived type is called after the Finalize method, the finalize method of the CriticalFinalizerObject derived type is called.

System.Runtime.InteropServices in the CriticalHandle class, in addition to not providing the reference counter function, other aspects and SafeHandle Classes are the same. The CriticalHandle class and its derived classes exchange for better performance by sacrificing security.

All types that define the Finalize method should implement the Dispose pattern described in this section at the same time, giving users of type more control over the lifetime of the resource. However, types can also implement Dispose mode, but do not define a Finalize method.

If a class defines a field and the type of the field implements the Dispose pattern, the class itself should implement the dispose pattern as well. The dispose method should be the object referenced by the Dispose field.

It is recommended that you call dispose or closeonly in the following two scenarios: Determine whether you must clean up resources (for example, in order to delete an open file), or make sure that you can safely call Dispose or close , and you want to remove the object from the finalization list, preventing the object from being promoted (to another generation), which improves performance.

If a class is to wrap a limited number of local resources, it should use System.Runtime.InteropServices 's handlecollector class to prompt the garbage collector how many instances of the resource it actually needs to consume. Objects of this class are internally monitored for this count, and when the count becomes larger, the garbage collection is enforced.

Inside,GC. The Addmemorypressure and Handlecollector.add methods invoke the GC. Collect method, forcing garbage collection to start before the No. 0 generation reaches the budget.

The system.runtime namespace provides a Memoryfailpoint class that allows you to check for ample memory before starting a large memory-consuming algorithm. Note, however, that the requested memory is not physically allocated. This means that the algorithm is only more likely to get the required memory and run successfully. The purpose of this class is simply to help you write more robust applications.

An excellent tool for monitoring the application's object assignment: CLR Profiler.

22nd. CLR Homestay and AppDomain

If a thread is executing code in a type's class constructor,catch block, or finally block, code in a CER, or unmanaged code, the thread is not in the security point.

Chapter 23rd assembly Loading and reflection

4 ways to reflect:

1. Use the InvokeMember of Type to bind and invoke a member.

2. Using FieldInfo, MethodInfo, PropertyInfo and other classes can be bound once, multiple calls. This technique can produce better-performing code.

3. Bind to an object or member, and then create a delegate to reference the object or member. This technique can produce code that is faster than the previous technology.

4. Use the dynamic primitive type of C # to simplify the syntax used when accessing members.

Use a binding handle (RuntimeTypeHandle, RuntimeFieldHandle, RuntimeMethodHandle) to reduce the memory consumption of the process.

24th Chapter Runtime serialization

You can use serialization to create a deep copy of an object, or to say a clone.

When serializing an object, the name of the type's full name and the type of the defined assembly is written to the stream. By default,BinaryFormatter outputs the full identity of the Assembly, including the assembly's file name (no extension), version number, language culture, and public key information. When deserializing an object, the formatter first obtains the assembly identity information and, through Assembly.Load , ensures that the assembly is loaded into the AppDomain being executed.

The best way to control the serialization and deserialization process is to use onserializing, OnSerialized, OnDeserializing, OnDeserialized, NonSerialized , and Optionalfield and other attribute.

The iserializationsurrogate interface can be used to take over a particular type of serialization and deserialization work (very rare).

You can use the System.Runtime.Serialization.SerializationBinder class to deserialize an object into a different type very simply. To do this, first define your own type and let it derive from the abstract class Serializaitonbinder .

26th. Asynchronous operation to calculate limits

If the callback method executes for a long time, the timer may fire again. This can cause multiple thread pool threads to execute your callback method at the same time. To solve this problem, my advice is: when constructing a Timer , specify timeout.infinitefor the period parameter. This way, the timer is triggered only once. Then, in your callback method, call the change method to specify a new duetime, and then specify timeout.infinitefor the period parameter again.

28th Chapter Primitive Thread synchronization constructs

When a thread communicates with each other through shared memory, call Volatilewrite to write the last value, calling Volatileread to read the first value.

Spin locks should only be used to protect areas of code that will execute very quickly.

There is a generic method Morph encapsulates the interlocked anything mode . It mainly solves the implementation of atomic methods in the case of multithreading (see Book p720-721).

delegateintMorpher<TResult, TArgument>(intstartValue, TArgument argument, outTResult morphResult);staticTResult Morph<TResult, TArgument>(refinttarget, TArgument argument, Morpher<TResult, TArgument> morpher){    TResult morphResult;    intcurrentVal = target, startVal, desiredVal;    do    {        startVal = currentVal;        desiredVal = morpher(startVal, argument, outmorphResult);        currentVal = Interlocked.CompareExchange(reftarget, desiredVal, startVal);    } while(startVal != currentVal);    returnmorphResult;}

CLR via C # Learning notes----General summary of Knowledge

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.