正在把自己以前整理的点PPT资料重新组织成文章发布出来。先发布两篇通用类型系统的文章:
以前我发布了一个我修改过的ADHelper类,似乎对于Active Directory活动目录使用者来说有点不够,为此我也希望在条件允许下,可以就我的有限经验讨论在.NET对活动目录的编程操作系列问题,毕竟活动目录是Windows Server的核心,相信我们日后或多或少都会接触到的。下面是几个活动目录的资料供入门学习,仅以开发人员角度出发:
- 为什么要有活动目录,什么是活动目录,它有什么用:活动目录主要用在分布式的环境中。在分布式环境中,要求有各种信息可以被各种应用很方便地访问读取。活动目录正式为分布式环境中的信息提供一种访问途径。它提供了一个公共的区域来保存分布式环境中的各种信息,并且对这些信息进行定位。
- 活动目录主要有什么:由于上面介绍的活动目录的特性,决定了它主要由一个保存这些信息的存储介质和允许用户访问这些信息的各种通讯协议两部分组成。
- 活动目录工具:
- Support Tools:位于WindowsServer安装光盘的SUPPORT\TOOLS目录下。安装完有Ldp.exe和ADSI Edit两个工具。通过ldp.exe可以用LDAP协议访问操作活动目录。通过ADSI Edit可以理顺你对活动目录层次关系及其信息组织方式。两个对你实际编程都非常有帮助。
- adminpak.msi:位于Windows\System32目录下。安装完在管理工具里可以查看到新增的功能项。主要是对于ActiveDirectory架构的查阅理解。
- DSML Service for Windows:通过微软网站下载。主要是通过标准的HTTP、XML、SOAP等对活动目录进行读写表达等操作。其中的DSDE工具主要用于目录里对象的导入导出等交换操作。
- 活动目录资料:
上面的资料肯定还是不够的,毕竟活动目录涉及太多,包括微软众多企业服务器产品。对于活动目录的编程,首先理解活动目录里的各种概念与应用场景是十分重要的。相信活动目录一定前景广阔J,没理由这么好的技术得不到广泛应用。
二、了解CTS前的准备
1、 首先,说说堆(heap)与栈(stack,也叫堆栈),理解了最起码的堆栈概念,对于理解CTS绝对是必要的,而在最近给公司新员工培训时,发现他们根本不了解这块,所以我也觉得有必要单独再稍微说明下。对于heap和stack,简单的来讲,stack上分配的内存系统自动释放,heap上分配的内存,系统不释放,哪怕程序退出,那一块内存还是在那里。stack一般是静态分配内存,而heap上一般是动态分配内存。也正因为它们这种特性,在.NET里,对于托管堆(managed heap)采取了通过垃圾回收器(Garbage Collection,简称GC)进行自动回收内存操作。下面是stack和heap的对比说明,可以让你更好理解它们:
l Stack:堆栈本身就具有回收特性,每当程序执行到区块的结束点时,该区块的内存就自动被释放(Last-In-First-Out,简称LIFO,后进先出),这让我们没必要担心程序里使用了多少变量,因为变量在区块外立即自动被释放,保证了一直有足够内存空间。堆栈虽好,但可惜的是并不是所有信息都可以存储在堆栈中。例如我们经常使用的string类型变量,之所以把string变量存储在Heap中,是因为字符串的长度是可变的,无法直接在堆栈中分配内存空间,因为堆栈是静态分配内存的。
l Heap:堆上的变量可以在任何地方被创建,在.NET里托管堆通过GC进行回收,至于回收方式,GC是通过标志方式进行回收的,即若有堆中的变量被标志为“待回收”,则未来GC会释放该内存空间。当然GC的回收远远不是这么简单,这里略过(有兴趣可以查看SDK文档或《深入理解.NET内存回收机制》一文)。
2、接着看下C#预定义类型:
|
运行时类型 |
C#预定义类型 |
描述 |
|
System.SByte |
sbyte |
8位有符号整数 |
|
System.Byte |
byte |
8位无符号整数 |
|
System.Int16 |
short |
16位有符号整数 |
|
System.UInt16 |
ushort |
16位无符号整数 |
|
System.Int32 |
int |
32位有符号整数 |
|
System.UInt32 |
uint |
32位无符号整数 |
|
System.Int64 |
long |
64位有符号整数 |
|
System.UInt64 |
ulong |
64位无符号整数 |
|
System.Char |
char |
一个16位Unicode字符 |
|
System.Single |
float |
单精度32位浮点数 |
|
System.Double |
double |
双精度64位浮点数 |
|
System.Boolean |
bool |
布尔值 true/false |
|
System.Decimal |
decimal |
128位数据类型 |
|
System.Object |
object |
根类 |
|
System.String |
string |
Unicode字符串 |
在.NET里,所有类型都是对象,而且都直接或间接继承自System.Object类。因此,例如我们声明并创建一个 int 类型时,实际创建了System.Int32的一个实例。例如:
|
1 |
public int i = 999; |
|
2 |
public int j; |
上面第1行代码,表示声明了一个 int 类型的变量 i,并赋值999。其实际是创建了 System.Int32 的一个实例,在堆栈Stack(为什么不是在heap堆上创建呢?这个后面会讲到是因为值类型和引用类型的区别)上分配一个内存空间存储了值999。
而第2行代码,只是声明了j,而没有进行赋值操作。在C#里,跟C++等不同的是,当你仅仅进行声明变量时,所发生的事就仅仅是“声明”,而没有进行实例的创建,也就没有进行内存空间的分配。例如,你声明了如下语句:
|
1 |
System.Web.UI.Page page; |
上面仅仅就是个声明而已,没有真正创建page实例,也就是说没有在内存空间里实际进行内存的分配。而你要进行创建实例,并进行内存分配,有且仅只有通过
|
1 |
System.Web.UI.Page page = new System.Web.UI.Page(); |
进行创建。也正因为这样,我们可以通过ILDASM看到上面声明的 j 实际是没有进行内存分配存储的。这也算是C#的一个新特征。这里额外也说了下。
下面是三个概念的理解:
l Managed Heap: 托管堆。是由CLR动态分配的连续的内存空间,在执行阶段由GC负责管理。整个进程共用一个托管堆。
l Call Stack: 这是由CLR在执行时自动管理的内存空间,每个线程都有自己的Call Stack。每调用一次方法,Call Stack就会多一次记录,调用完毕该记录随即被丢弃。
l Evaluation Stack:这是由CLR在执行时自动管理的内存空间,每个线程都有自己的Evaluation Stack。事实上,我们在CTS里常说的线程堆栈指的就是它。
通用类型系统(Common Type System,以下简称CTS,有的地方也叫公共类型系统),算是个老话题了,但对于部分.NET程序员来说,可能还是需要这方面的知识。加上CTS是.NET里各种语言的基础,为了更好的进一步学习各种语言特性以及.NET Framework,也不得不了解CTS。我近期也在准备着一些.NET入门到提高学习资料,所以顺便整理下相关资料贴出来供大家参考(有可能的话,会按我整理的从入门到提高的系列一篇篇贴出来,不过就是要等待些时间),哪怕你对其中一点有心领神会的感觉,那也就够了。OK,转入正题。
一、CTS简介
我们都知道,编程语言发展至今已经有几百种,面对这么多的编程语言,经常有人陷入类似“生死抉择”的痛苦,但是有点体会的程序员总会说:“语言是互通的,只要你掌握了编程思想,遵循相应编程规范,就不用怕今天又出现了多少新语言”。我想这句话确实是有道理的。在这众多语言的背后,也隐藏着某种共性,不仅在语言本身,也在使用语言的方法上。就象大家常理解“程序=算法+数据结构”一样,我们也可以这样理解语言的共性,即“语言=语法+语义”。单纯字面上理解(不涉及编译等具体技术),语言实际上就是用各种事先定义好的关键字以一种特定组合方式起来的表现形式,用以定义数据以及描述对数据的操作。
了解了语言的概念,让我们思考下,是否存在一种东西(请原谅我用“东西”这个词)满足所有语言的共性?假如众多语言有了一种共性,是否可以进一步让众多语言之间实现互操作?再者,结合面向对象里的单根对象层次观点让每个对象最终都有相同的基类型,是否就又有了类型的统一功能?接着在统一类型基础上,又有了统一的调试方式、统一的体系框架、统一的开发手段等等呢?好了,再说下去都成完美神话了。上面的“东西”,实际上就是CTS。也正因为有了CTS,才有了.NET里“统一”的诸多特性,把CTS说成CLR(Common Language Runtime 通用语言运行库)的核心,编程人员必须掌握的特性一点也不为过。
下面引用MSDN里的CTS定义让大家有更清楚了解CTS,毕竟MSDN是权威:
|
通用类型系统定义了如何在运行库中声明、使用和管理类型,同时也是运行库支持跨语言集成的一个重要组成部分。通用类型系统执行以下功能:
- 建立一个支持跨语言集成、类型安全和高性能代码执行的框架。
- 提供一个支持完整实现多种编程语言的面向对象的模型。
- 定义各语言必须遵守的规则,有助于确保用不同语言编写的对象能够交互作用。
|
清楚了CTS的概念与优点后,我们更进一步来了解CTS。按照上面所讲的语言与CTS的关系,我们可以把CTS看成是.NET是所有语言的超集,也就是说各种符合CTS的语言,实际上都是CTS的一个子集。用数学的集合观点理解就是如下图:

从上图还可以看出在各种语言之间还有个交集——通用语言规范(Common Language Specification,简称CLS),这里也简单说下。我理解中,CTS是一套类型系统,而CLS则是事先定义好的一种规则,遵循这种规则编写的任何代码都可以实现跨语言的互操作性。事实上,通用语言基础结构(Common Language Infrastructure, 简称CLI,是CLR的子集。CLR与CLI的关系类似CTS与CLS的关系。)正是使用CLS来让各种不同的语言使用.Net框架各种资源。在实际应用上,对于CLS,如果我们项目里都只用一种语言,例如C#,那就没必要过度关心CLS。相对地,如果是多种语言结合开发,或者希望你开发的类库能让各种不同语言调用时,那么CLS绝对是你需要进一步了解的内容。