CLR via C# 3rd - 04 - Type Fundamentals

 

1. System.Object
 
     The runtime requires every type to ultimately be derived from the   System.Object  type.
 
     Because all types are ultimately derived from System.Object, you are guaranteed that every object of every type has a minimum set of methods. Specifically, the System.Object class offers the   public  instance methods listed in below.
 
      Equals
     GetHashCode
     ToString
     GetType
 
     In addition, types that derive from System.Object have access to the   protected  methods listed in below.
 
     MemberwiseClone
     Finalize
 
     The CLR requires all objects to be created using the new operator.
  
2. new
 
     Here’s what the   new  operator does:
 
     1. It   calculates the number of bytes required  by all instance fields defined in the type and all of its base types up to and including System.Object (which defines no instance fields of its own). Every object on the heap requires some additional members—called  the type object pointer and the sync block index—used by the CLR to manage the object. The bytes for these additional members are added to the size of the object.
 
     2. It allocates memory for the object by allocating the number of bytes required for the specified type from   the managed heap; all of these bytes are then set to   zero  (0). 
 
     3. It initializes the object’s type object pointer and sync block index members. 
 
     4. The type’s instance constructor is called, passing it any arguments (the string "ConstructorParam1" in the preceding example) specified in the call to new. Most compilers automatically emit code in a constructor to call a base class’s constructor. Each constructor is responsible for initializing the instance fields defined by the type whose constructor is being called. Eventually,  System.Object’s constructor is called, and this constructor method does nothing but return. You can verify this by using ILDasm.exe to load MSCorLib.dll and examine System.Object’s constructor method.
 
3. Casting Between Types
 
     One of the most important features of the CLR is type   safety. At runtime, the CLR always knows what type an object is. You can always discover an object’s exact type by calling the  GetType  method. Because this method is nonvirtual, it is impossible for a type to spoof another type.
 
      The CLR allows you to cast an object to its type or to any of its base types.
 
       C# doesn’t require any special syntax to cast an object to any of its base types, because casts to base types are considered safe implicit conversions. However, C# does require the  developer to  explicitly cast an object to any of its derived types  since such a cast could fail at runtime.
     
      System.InvalidCastException
 
4. Castring with the C#   as  and   is  Operators
 
     The   is   operator  checks whether an object is   compatible  with a given type, and the   result  of the evaluation   is a Boolean: true or false. The is operator will   never throw an exception.
 
     The is operator is typically used as follows:
 
if (o is Employee) {
Employee e = (Employee) o;
// Use e within the remainder of the 'if' statement.
}
 
     The CLR’s type checking  improves security, but it certainly   comes at a performance cost, because the CLR must determine the actual type of the object referred to by the variable (o), and then the CLR must walk the inheritance hierarchy, checking each base type against the specified type (Employee). Because this programming paradigm is quite common, C# offers a way to simplify this code and improve its performance by providing an   as   operator
 
Employee e = o as Employee;
if (e != null) {
// Use e within the 'if' statement.
}
 
      Notice that the as operator causes the CLR to verify an object’s type just once. The   as operator  works just as   casting  does except that the as operator will   never throw an exception. Instead, if the object can’t be cast, the result is   null.
 
5. namespaces and assemblies
 
     using namespace;
 
     Be aware that a namespace and an assembly (the file that implements a type) aren’t necessarily related. In particular, the various types belonging to a single namespace might be implemented in multiple assemblies.
 
6. How things relate at Runtime
 
      Stack space  is used for passing arguments to a method and for local variables defined within a method.
 
     All but the simplest of methods contain some   prologue code, which initializes a method before it can start doing its work. These methods also contain   epilogue code, which cleans up a method after it has performed its work so that it can return to its caller.
 
     When a method is called, the arguments will be pushed on the stack firstly,  then the address indicating where the called method should return to in the calling method is pushed on the stack.
 
     The Progress:
     
     (1) As the just-in-time (JIT) compiler converts method's Intermediate Language (IL) code into native CPU instructions, it notices all of the types that are referred to inside the method. At this time,   the CLR ensures that the assemblies that define these types are loaded.  Then, using the assembly’s metadata, the CLR extracts information about these types and creates some data structures to represent the   types themselves.
 
     (2) All objects on the heap contain two overhead members:   the type object pointer and the sync block index.
 
     (3) When you define a type, you can define static data fields within it.   The bytes that back these static data fields are allocated within the type objects themselves. Finally, inside each type object is a method table with one entry per method defined within the type.
 
     (4)  Whenever  a   new object  is created  on the heap, the   CLR  automatically   initializes  the internal   type object pointer  member   to refer to  the object’s corresponding   type object.
 
     (5)  Furthermore, the   CLR  initializes the   sync block index  and   sets  all of the object’s   instance fields to null or 0  (zero) prior to calling the type’s constructor, a method that will likely modify some of the instance data fields. 
 
     (6) When   calling  a   static method, the   JIT compiler   locates the type object that   corresponds to the type that defines the static method.   Then, the   JIT compiler locates  the entry in the type object’s   method  table that refers to the method being called,   JITs the method  (if necessary), and   calls the JITted code.
 
     (7) When   calling  a   nonvirtual instance method, the   JIT compiler locates  the   type object  that corresponds to the type of the variable being used to make the call.  JIT compiler walks down  the   class hierarchy toward Object  looking for this method. It can do this because each type object has a field in it that refers to its base type. Then, the JIT compiler locates the entry in the type object’s method table that refers to the method being called, JITs the method (if necessary), and then calls the JITted code.
 
     (8) When   calling  a   virtual instance method, the   JIT compiler produces some additional code in the method, which will be executed each time the method is invoked. This code will   first look in the variable  being used to make the call and then follow the address to the   calling object. Then,   the code will   examine  the object’s internal   type object pointer  member; this member refers to the actual type of the object.   The code  then   locates  the entry in   the type object’s method table that refers to the method being called, JITs the method (if necessary), and calls the JITted code.
 
     (9)  Type objects are actually objects  themselves, so they all contail   type object pointer. When the CLR creates type objects, the CLR must initialize these members. 
 
     (10) When the   CLR starts running in a process,   it immediately creates a special type object for the System.Type type  (defined in MSCorLib.dll).
 
     (11)  System.Type  type object is an object itself and therefore   also has a type object pointer  member in it, and it is logical to ask what this member refers to.   It refers to itself  because the System.Type type object is itself an “instance” of a type object.
 
     (12) By the way,  System.Object’s   GetType  method simply   returns the address stored in the specified object’s type object pointer member. In other words, the   GetType method returns a pointer to an object’s type object, and this is how you can determine   the true type of any object  in the system (including type objects).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

转载于:https://www.cnblogs.com/junier/p/3577956.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值