CLR via C # version 4
JIT Performance
Why is there sometimes a JIT language faster than a language that directly compiles machine code?
In short, JIT knows more information than the compiler that directly compiles the code into a machine on the development machine. Sometimes the information is so useful, so that the effect can exceed the JIT overhead and the limited JIT compilation time. CLR provides three specific reasons:
In addition, I think there is another important reason:
JIT can be optimized and inline across the boundaries of assembly files. These assembly may be compiled at different times and on different machines. Traditional compilers cannot do anything about this.
Checked keyword
The scope of the checked keyword is only within the current function, and does not affect the function called in the checked block. Therefore, the following code does not throw an exception.
Main( a = +=
In fact, it is normal to think about it. The purpose of the checked keyword is to compile the value calculation into an IL command with a check. If the called function is in another Assembly, the Assembly has already been compiled, how can it be changed?
However, note: Decimal is not a basic type. The four arithmetic operations do not correspond to the IL command, so it is not affected by the checked operation and will always throw an exception.
Value Type and reference type
Value Type indicates that this object is not allocated to the pair, and the value type itself may be included in a reference type, so the value type may not be on the stack.
The Value Type also uses the new Keyword, which may cause misunderstanding.
The value type can overlap multiple value type fields by specifying the display.
Only C ++/CLI can obtain a pointer to the boxed value type. C # can only be split first.
When used as a template type parameter, the value type forces CLR to generate a specific code for it, and only the referenced template instance can share the code to reduce memory usage.
Personal experience:
The reference type new has only one instance at a time, but the value type is not necessarily. The value type is passed and modified, and its behavior requires careful analysis of the lifetime of each value type variable, it brings a lot of burden to developers, including the so-called packing box. We recommend that you use it only in a local range or when it is a read-only object, because C # code farmers generally do not have the ability to clearly grasp the object survival as C ++ code farmers do, it is easy to be killed by pig teammates.
GC Problems
During GC collection, even if an object does not exceed the survival range (Block) in the C ++ sense ), however, because the code that is not run below is not referenced, GC is considered not referenced. In/debug mode, the object lifetime is extended to the end of the function body.
Timer t = Timer(TimerCallback, , , Console.WriteLine( + DateTime.Now);
When the process ends normally, CLR also executes the GC process and releases the object.
CriticalFinalizerObject
For unmanaged resources, we recommend that you use the SafeHandle series to manage their handles. Its base class CriticalFinalizerObject has the following additional features supported by CLR:
In addition:
Miscellaneous
The dynamic type is processed as Object + DynamicAttribute, so different overloading cannot be implemented through Object and dynamic.
The value of const will be inline during compilation, but the value of readonly will not. Therefore, the value that may need to be changed in the future should not be const.
When the Nullable type is packed, CLR will handle it specially. Remove Nullable, that is, null is packed into null, v is packed into v, rather than Nullable <V> type.
You can use the FirstChanceException event of AppDomain to monitor whether an exception is thrown, but the Event Callback Function cannot handle this exception.
If an exception is not handled by the CLR and reported to Windows Error Reporting, the call stack obtained by the exception can only be at the most recent throw or re-throw location, that is, re-throw is invalid for Windows Error Reporting and will reset the exception throw point.
In Catch and Finally blocks, the thread will not be interrupted by Abort.
Environment. FailFast can skip normal Exception Handling logic and object Finalize method to directly end the process.
If an exception is thrown when a reflection call is used, the exception is wrapped in TargetInvocationException; dynamic is not affected.
Constrained Execution Regions (CERs), which allows the CLR to "prepare" a piece of code before the try block in advance, instead of throwing an exception during the running process due to DLL loading failure or class static initialization failure.
Thread. sleep (0) can give the CPU to threads with the same or higher priority, while Thread. yield can give the CPU a lower priority, between Thread. sleep (0) and Thread. between Sleep (1.