zoukankan      html  css  js  c++  java
  • .NET本质论

    Technorati 标签: ,

    1. CLR是一个更好的COM。从COM开发人员所面临的问题入手,讲述了CLR如何应用虚拟化以及无所不在的、可扩展的元数据,解决这些COM问题,从而最终取代COM。

    2. 组件。从根本上讲,CLR是OS和COM加载器的替代品,本章讨论了代码是如何封装和加载的,它们与Win32和COM世界中的情形大相径庭。

    3. 类型基础。组件是代码和构成f类型定义的元数据的容器。本章重点讨论了通用类型系统(Common Type System, CTS),包括类型的组成部分,以及类型是如何关联的。

    完全限定的类型包括3个部分:程序集名字、可选的命名空间前缀和类型名称。类型可以包括3类成员:字段、方法和嵌套类型。

    类型的字段控制内存如何分配,CLR在第一次使用类型的时候初始化static字段的值,在创建对象的时候会初始化实例字段的值。const字段和readonly,const=static readonly。

    方法。静态方法和实例方法,方法重载。

    嵌套类型。CLR将嵌套类型当做声明类型的静态成员,它不隶属于任何特定实例。嵌套类型的名字由外部类型名字限定,由于嵌套类型是外部类型的一部分,它能够访问外部类型的private字段。反之,外部类型并不能访问嵌套类型的private字段。

    类型和初始化。类型初始化器,也就是static构造函数,每个类型只能有一个,没有参数,也没有返回值。静态字段声明在静态构造函数前面执行。

    类型和接口。

    类型和基类型。成员重载overloading和隐藏shadowing。

    clip_image001

    clip_image002

    构造函数的执行顺序。C#和C++的处理策略不一样。

    派生和构造,c#。

    clip_image003

    4. 用类型编程。在编程模型中,CLR将类型作为第一类概念。本章讨论了CLR程序中类型的显式用法,主要是元数据与运行时类型信息的角色。

    a.运行时的类型。类型的实例分为值和对象,每个对象有一个“对象头”:一个同步块索引字段和一个指向对象类型的句柄。

    对象头和类型句柄

    clip_image004

    每个类型都有一张接口表,包含了类型兼容的接口的入口项,对接口类型的转换通过这张表匹配;为了支持向直接或间接基类型的转换,类型结构还有一个指向基类型的指针。

    类型的层次结构和运行时的类型信息

    clip_image005

    类型信息的数据结构可以通过Type访问,比如判断继承关系,可以用Type对象的IsSubClassOf或IsAssignableFrom,IsValueType判断是否值类型等等。

    元数据编程。一般元数据编程是用来生成代码,这里只讨论读取元数据。

    反射对象模型。其中Type.GetMembers可以获得类型中的全部的成员:字段、方法和嵌套类型

    clip_image006

    反射类型的层次结构

    clip_image007

    Type.GetMembers默认返回Type的公有约定中的部分成员,同时不包括静态成员,要想得到其他的成员,可以通过BindingFlags枚举指定。

    using System;
    using System.Reflection;
    public sealed class Util
    {
        public static void DumpMembers(Type type)
        {
            // get the type's members
            BindingFlags f = BindingFlags.Static
            | BindingFlags.Instance
            | BindingFlags.Public
            | BindingFlags.NonPublic
            | BindingFlags.FlattenHierarchy;
            MemberInfo[] members = type.GetMembers(f);
            // walk the list of members
            for (int i = 0; i < members.Length; i++)
                Console.WriteLine("{0} {1} ",
                members[i].MemberType,
                members[i].Name);
        }
    }

    使用反射的一个例子

    5. 实例。CLR编程模型是基于类型、对象和值的。第四章讨论类型,本章则重点讨论对象和值。特别是概述了这两种实例模型的差别,包括值与对象在内存管理方面的不同。

    6. 方法。所有组件之间的交互都是在方法调用中体现出来的。CLR提供了一系列技术,使得方法调用成为清晰的行为。本章将介绍这些技术,从实时编译时的方法初始化开始,直到类型异常时的方法终止。

    方法和JIT编译。每个类型都有一张方法表,下面的例子是方法f调用情况。

    class Bob {
        static int x;
        static void a() { x += 2; }
        static void b() { x += 3; }
        static void c() { x += 4; }
        static void f()
        { c(); b(); a(); }
    }

    方法f对应的本机代码native code。

    clip_image008

    方法表的每个入口项指向一个唯一的存根例程(sub routine),初始化时,每个存根例程包含对CLR的JIT编译器的调用(PreStubWorker),在JIT编译器生成本机代码后,它会重写存根例程,插入一个jmp指令跳转到刚才生成的代码。

    下图是的JIT编译和方法表,是JIT刚好编译f和c后的快照。

    clip_image009

    下图显示了JIT编译前后的方法存根

    clip_image010

    方法调用和类型。方法调用的CIL是call,虚方法调用对应的是callvirt。CIL的call指令静态地绑定本机IA-32指令到特定类型的方法表,callvirt产生一个特别的指令,它将根据目标对象的类型决定使用哪张表。每个类型的方法表中第一个区域是虚方法,包含基类的虚方法(最前面的是object的4个虚方法),第二个区域是非虚方法。

    clip_image011

    虚方法调用对应的native代码。第一句将this指针放到ecx中,第二句将类型句柄放到eax中,第三句根据方法表的偏移量调用方法。这个偏移量是类型加载时算出来的,不同的加载可能不一样,但是在一次加载中是不变的。

    move ecx, esi
    move eax, dword ptr [ecx]
    call dword ptr [eax + 38h]

    newslot和虚方法。每个虚方法在方法表中有一个插槽slot,如果虚方法声明为newslot,那么会分配一个新的插槽,这个插槽在所有基类型虚方法的后面;如果没有声明为newslot,那么会替换基类型中的相同签名的方法。

    clip_image012

    clip_image013

    接口、虚方法和抽象方法。每个CLR类型都有一个方法表,CLR是这样安排这个方法表的:对于一个特定的声明接口,它的所有方法表插槽都是连续的。但是对于不同的类型,接口的方法表绝对位置可能不同,CLR使用接口偏移量表(interface offset table)来指名位置。

    clip_image014

    图6.4 使用基于接口引用的虚函数

    C#支持两种实现接口方法的技术:一种是作为带有相同签名的公有方法,一种是实现相同签名的私有方法,方法名必须遵循InterfaceName.MethodNam的约定。例如对于接口IDrawable的Display方法,其实现的方法名为Idrawable.Display。前一种实现方法成为类公有签名的一部分,后者只能通过up-cast成接口才能访问。注意第二个Clone如果声明为public编译会报错(修饰符“public”对该项无效)。

    clip_image015

    clip_image016

    CLR认为接口的方法是virtual的,也就是方法放在接口表的virtual部分,类继承接口如果没有显式声明virtual,CLR会当做virtual sealed处理(c#不能将同时使用virtual和sealed),也就是其派生类不能再override。下面是继承接口的例子。

    clip_image017

    判断下面例子中几个DoIt调用的方法。

    clip_image018

    第一个调用方法e,第二个调用e,第三个调用b,第四个调用c。想象下ReallyDerived方法表

    显式方法调用。

    7. 高级方法。CLR提供了强大的架构用来侦听方法调用。本章剖析了CLR侦听的实用部件,以及它对面向方面编程(aspect-oriented programming)的支持。

    8. 域。CLR采用了AppDomain而不是OS进程,来划分代码的执行范围。本章从两个方面讨论AppDomain的角色,即作为底层OS进程的替代品,以及一个AppDomain与程序集解析器或加载器之间的交互。

    9. 安全性。CLR一个主要的优点就是提供安全运行的环境,本章阐述了CLR加载器如何支持想代码授予特权,以及这些特权如何被强制实施的。

    10. CLR外部环境。前9章都是讨论基于CLR编程模型的程序设计,最后一章则关注该编程模型对外的方式,以及它如何处理外部世界。

  • 相关阅读:
    安卓开发_浅谈Android动画(三)
    安卓开发_浅谈Android动画(二)
    安卓开发_浅谈Android动画(一)
    Go语言获取系统性能数据gopsutil库
    Go语言标准库之log
    选项模式
    Go语言标准库之template
    Go语言基础之切片
    Go语言基础之反射
    Go语言基础之运算符
  • 原文地址:https://www.cnblogs.com/lingshf/p/6653684.html
Copyright © 2011-2022 走看看