.NET本质论

Technorati 标签: .NET,C#

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。

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

派生和构造,c#。

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

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

对象头和类型句柄

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

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

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

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

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

反射类型的层次结构

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。

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

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

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

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

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

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

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

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

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

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

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

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

第一个调用方法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编程模型的程序设计,最后一章则关注该编程模型对外的方式,以及它如何处理外部世界。

时间: 2024-10-17 13:55:44

.NET本质论的相关文章

《COM本质论》读书笔记

前言 虽然一直都不喜欢Windows的应用开发,不过由于现在工作需要,必须对 Win32 开发非常熟悉. Windows 上的 C++ 开发,逃不过对组建对象模型COM(Component Object Model)编程的学习和理解,尤其是游戏.音视频领域 —— Direct3D/Direct2D/DirectShow/DirectSound 等等.COM已经是上个世纪的产物了,所以相关的学习资料也都很老了,不过<COM本质论>是一本不错的入门书.在此我做做笔记加深理解. 第1章:COM是一个

从构造函数说开去---C#本质论读书笔记

记得一年之前在写代码的时候问了小伙伴一个问题,我说:“你说如果我在声明的时候初始化,它会在对象初始化的哪个阶段被赋值?” 小伙伴想了想回答我:“还是在构造函数里面给变量初始化吧.” 程序当口,时间比较紧,没有空去验证一下这个问题,后来也就慢慢淡忘了. 这个假期翻开“C#本质论”正好里面也提到了这种情况,虽然只是一笔带过,但是也勾起了我的回忆,那今天就来记录一下这个疑问以及它延伸出来的一些知识点. 1.普通构造函数 public class ConstructionTest    {       

闭包在.NET下的实现(编译器玩的小把戏)-----C#本质论读书笔记

参加工作以来,拜读过很多大作.有好多书读的时候感觉大彻大悟,不自觉的发出‘哦...’这样的感叹.但是随着杀猪刀(时间)不断的飞逝,不仅给我脸上带来了皱纹,还带走了不少前人总结和归纳的知识点和那些我还没来得及吸收的宝贵财富.好记性不如烂笔头,我决定开始写一些读书的笔记和工作上的心得,最好是两者能够结合起来,把知识真正的自己转化成自己的能力. 下面进入正题.闭包在程序员的日常工作几乎无所不在,当然不仅是工作,面试的时候经常也会有相关的题目.看过很多博客园上的朋友都有解释,每次重温都有‘哦...’的感

《COM本质论》COM是一个更好的C++心得分享

昨天看了<COM本质论>的第一章"COM是一个更好的C++",认为非常有必要做一些笔记,于是整理成这篇文章.我相信你值得拥有. 这篇文章主要讲的内容是:一个实现了高速查找功能的类FastString,在一个小小的需求之后,慢慢的演变成一个COM组件的过程. 类FastString实现了一个高速查找字符串的功能.快到时间复杂度是O(1),我们先无论作者是怎么实现的,预计是通过空间换时间. 因为这个类查找字符串非常快,于是作者就把这个类当做一个产品,以源代码的方式卖给须要的厂商

2017-07-20聊聊《C#本质论》

第一次接触<C#本质论>是在这个链接.那时候刚学写C#,而且它的语言风格深深吸引了我,噢对了还有它强大的IDE--VS.这个链接里的书确实不错.文中提到: 虽然这三本书都是外国原著的,但是却不像其他系列书一样中文译版和原版版本相差很大,可以说翻译工作几乎同步. 1. <果壳中的C#> 去年双十一在亚马逊看到原版书(第四版)降价,好不容易下单了,等了一个月没发货(海外淘)就取消订单了.在图书馆看过最新的中文版本也就第三版,没看过没太多话语权,等下学期预约了这本书(太抢手了!)看看再写

C#本质论学习笔记

C#本质论和CLR via C#两本好书,周老师可能是俗务缠身,太忙了吧,翻译得只能让人呵呵了. 你要是忙,别接那么多活好不啦,否则岂不误人子弟? 请您好好学习一下李建忠老师吧,差距啊. 这里,把随手发现的一些问题记录一下,算个笔记.若能对其它同学有所帮助,就更好了. C#本质论第四版 7.3.3 显式接口实现与隐式接口实现的比较 原文: The key difference between implicit and explicit member interface implementatio

《C#本质论》读书笔记(18)多线程处理

.NET Framework 4.0 看(本质论第3版) .NET Framework 4.5 看(本质论第4版) .NET 4.0为多线程引入了两组新API:TPL(Task Parallel Library,任务并行库)和PLINQ(Parallel LINQ,并行LINQ). 18.1 独立线程的运行和控制 通过 System.Threading.Tasks.Task 类在托管代码中公开各种API,该类代表的是一个异步操作.然而,一个 Task 并不直接映射到一个非托管线程.相反, Tas

[Asp.net本质论]学习笔记(1)

引言 之前大部分时间,一直在学c#,打算将asp.net本质论好好学习一下,之前虽然已经看了两边了,总感觉看过,没做笔记等于白看了,一点印象也没.打算将书中的代码,自己实现一下,在敲代码时要一直反思,为什么作者那样实现,如果是自己该如何实现? web应用程序 资源的地址——通用资源标识符(URI) 我们在浏览器地址栏中输入的内容统称为通用资源标识符(Universal Resource Identifier,URI),它有很多种形式,在web中我们通常使用统一资源定位符(Uniform Reso

1.网站应用程序 - 《APS.NET本质论》

1.1.HTTP协议 浏览器与WEB服务器的协议是应用层协议,当前遵循HTTP/1.1,HTTP协议是无状态的协议 客户机与服务器通过请求和响应完成一次会话(Session),每次会话中,双方发送的数据称为消息(Message),消息分为两种: 请求消息和回应消息. 客户端请求消息 客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行(request line).请求头部(header).空行和请求数据四个部分组成,下图给出了请求报文的一般格式. 服务器响应消息 HTTP响应也由四个