zoukankan      html  css  js  c++  java
  • CTS、CLS、CLR

    CTS

      一个给定的程序集可能包含任意数量的不同“类型”。在.NET领域,类型(type)是一个一般性的术语,它指的是集合{类,接口,结构,枚举,委托}里的任意一个成员。当用支持.NET的语言构建解决方案时,很有可能要与这些类型打交道。例如,程序集可能定义了一个类,它又实现了一些接口。或许其中某个接口方法采用枚举类型作为输入参数,而在调用时返回一个结构。

      CTS(公共类型系统)是一个正式的规范,它规定了类型必须如何定义才能被CLR承载。通常,只有那些创建针对.NET平台的工具或编译器的人才对CTS的内部工作非常关心。但是,对于所有.NET编程人员来说,学习如何在自己使用的语言中使用由CTS定义的5种类型,是非常重要的。这里简单概括一下。

    CTS类类型

      每一种支持.NET的语言至少要支持类类型(class type)的概念,这是OOP的基础。类可能由很多成员(诸如构造函数、属性、方法和事件)和数据点(字段)组成。在C#中,使用class关键字来声明类。

      表1-1给出了有关类类型的一些特征。

    表1-1 CTS类类型

    类的特征 在生命周期里的意义
    类是否被“密封” 密封类不能作为其他类的基类
    类实现任何接口了吗 接口是抽象成员的集合,它在对象和对象的用户间提供一个契约。CTS允许类实现任何数目的接口
    类是具体的还是抽象的 抽象类是不能直接创建的,但是可以用来为派生类型定义公共的行为。具体类可以直接创建
    这个类的可见性是什么         每个类必须用关键字(public或internal)设置可见性。基本上,可见性定义了该类是被外部程序集使用,还是仅能在定义了它的程序集中使用

    CTS接口类型

      接口(interface)就是由抽象成员定义所组成的一个具名集合,可通过一个给定的类或结构来实现。在C#中,接口类型使用interface关键字来定义。一般情况下,所有的.NET接口均以大写字母I开头。

      就它们自身而言,接口没有什么用。然而,当一个类或结构用其独特方式来实现一个给定接口时,你将能够以多态方式通过接口引用来请求使用所提供的功能。

    CTS结构类型

      CTS中还支持结构(structure)的概念。简单地说,结构(struct)可以看做是具有值语义的轻量级类类型。通常,结构最适合建模几何和数学数据。在C#中,通常使用struct关键字创建结构。

    CTS枚举类型

      枚举(enumeration)是一种便利的编程结构,它可以用来组成名称/值对。例如,假设你在开发一个视频游戏的程序,要让玩家在3种角色(Wizard、Fighter或Thief)中选择一个。你完全可以用enum关键字来建立一个自定义的枚举,而不用老是要记着代表每种可能性的原始数字值。

      在默认情况下,每一项是用一个32位的整数来存储的,但如果需要,也可以改变存储大小(例如,在为Windows移动设备之类的低内存设备编程时)。另外,CTS要求枚举类型派生自基类System.Enum。这个基类定义了一些有趣的成员,允许通过编程提取、操作和变换底层的名称/值对。

    CTS委托类型

      委托(delegate)在.NET中等效于类型安全的C风格的函数指针。它们的主要不同在于,.NET委托是派生自System.MulticastDelegate的类,而不是一个简单地指向原始内存地址的指针。在C#中,委托是使用关键字delegate来声明的。

      一个实体可以用委托向另一个实体传递调用,另外,委托也为.NET事件架构提供了基础。委托对多路广播(即将一个请求转发给多个接收者)和异步方法调用(即从另一个线程调用方法)有着内在支持。

    CTS类型成员

      现在你已经看到了由CTS正式规定的各种类型,但还要认识到,大部分的类型可以含有任意数量的成员。说得更正式一些,类型成员是集合{构造函数,终结器,静态构造函数,嵌套类型,操作符,方法,属性,索引器,字段,只读字段,常量,事件}中的元素之一。

      CTS定义了各种可能与具体成员关联的修饰语(adomment)。例如,每个成员都有一个给定的可见性特征(如公共的、私有的和受保护的等)。有些成员可能被声明成抽象的以加强派生类的多态性,有些成员可声明为虚拟的以定义一个封装(但可重写)的实现。同样,绝大部分成员可设置成静态的(在类级别绑定)或者实例(在对象级别绑定)。

    內建的CTS数据类型

      CTS需要关注的最后一个方面是,它建立的一套定义明确的核心数据类型。尽管不同的语言通常都有自己唯一的用于声明內建CTS数据类型的关键字,但是所有语言的关键字最终将解析成定义在mscorlib.dll程序集中的相同类型。参考表1-2,它描述了如何在不同的.NET语言中表示关键的CTS数据类型。

    表1-2 內建的CTS数据类型

    CTS数据类型 VB关键字 C#关键字 C++/CLI关键字
    System.Byte Byte byte unsigned char
    System.SBtye SByte sbyte signed char
    System.Int16 Short short short
    System.Int32 Integer int int 或 long
    System.Int64 Long long _int64
    System.UInt16 UShort ushort unsigned short
    System.UInt32 UInteger uint  unsigned int 或 unsigned long
    System.UInt64 ULong ulong unsigned _int64
    System.Single Single float Float
    System.Double Double double double
    System.Object Object object object^
    System.Char Char char wchar_t
    System.String String string String^
    System.Decimal Decimal decimal Decimal
    System.Boolean Boolean bool bool

      由于各种委托语言的关键字只是System命名空间中真实类型的简化符号,我们不需要担心数值数据的上溢或下溢,或是字符串和布尔型数据在内部是怎样跨不同语言进行表示的。下面的代码片段使用C#和VB,通过语言关键字和正式的CTS数据类型分别定义了32位数值变量。

    // 用C#定义整型数据
    int i = 0;
    System.Int32 j = 0;
    ' 用VB定义整型数据
    Dim i As Integer = 0
    Dim j As System.Int32 = 0

    CLS

      不同的语言往往用不同的、语言特定的术语表达相同的程序构造,比如,在C#中使用加号(+)操作符表示字符串拼接,而在VB中却使用“&”符号。即使两种不同的语言表达相同的编程惯用法(比如一个不返回值的函数),在表面看起来,语法也可能非常不同。

      在.NET运行库看来这些较小的语法变化是微不足道的,因而不同的编译器(这里用到的是vbc.exe或csc.exe)将产生类似的CIL指令集。然而,语言也可能在功能上不同,比如,.NET语言可能有也可能没有关键字来表示无符号数据,可能支持也可能不支持指针类型。对于这些可能的变化,理想情况是所有支持.NET的语言都有一个可以遵循的基准。

      CLS就是这样一套规则,它清晰地描述了支持.NET的编译器必须支持的最小的和完全的特征集,以生成可由CLR承载的代码,同时可以被基于.NET平台的其他语言用统一的方式进行访问。CLS可以看成是由CTS定义的完整功能的一个子集。

      如果打算让自己的产品功能无缝地融合到.NET世界,那么CLS是编译器创建者最终必须要遵循的一套规则。每个规则被赋予一个简单的名字(如CLS规则6),描述了这个规则如何影响创建编译器的人以及(以某种方式)与他们交互的人。影响最大的是规则1。

    • 规则1:CLS规则仅适用于类型中向定义它的程序集以外公开的部分。

      根据这个规则,可以(正确地)推断其余的CLS规则对于用来建立一个.NET类型内部运行功能的逻辑是不适用的。必须遵循CLS的类型的唯一一点,就是成员定义本身(即命名规范、参数和返回类型)。成员的实现逻辑可以使用其他的非CLS技术,程序外部并不知道这些不同。

      举例说明,下面的Add()方法就没有遵循CLS规则,因为它的参数和返回值使用了无符号数(无符号数不符合CLS):

    class Calc
    {
        //公开的无符号类型数据不遵循CLS规则
        public ulong Add(ulong x, ulong y)
        { return x + y; }
    }

      然而,如果像下面一样在程序内部使用无符号数:

    class Calc
    {
        public int Add(int x, int y)
        {
            // 当ulong类型变量仅仅在内部使用时,仍然遵循CLS规则
            ulong temp = 0;
            ...
            return x + y;
        }
    }

      这仍然遵循CLS规则,可以保证所有的.NET语言都能调用Add()方法。

      当然,除规则1外,CLS还定义了很多其他的规则。例如,CLS描述了一种语言如何表示文本字符串,如何在内部表示枚举(用于存储的基类型),如何定义静态成员,等等。好在你不需要记忆所有的规则也能成为静态.NET的程序员。总地来说,只有那些工具/编译器的开发人员才会对CTS和CLS规范的具体细节感兴趣。

    确保遵循CLS

      C#定义了一些不遵循CLS规则的程序结构,但你仍然可以使用一个专门的.NET特性指示C#编译器检查代码是否遵循CLS规则。

    // 指示C#编译器检查是否遵循CLS规则
    [assembly:CLSCompliant(true)]

      目前,只需要知道[CLSCompliant]特性就是用来指示C#编译器按CLS规则检查每行代码的。如果代码违反了CLS,就会给出编译器错误和关于错误代码的描述。

    CLR

      从编程角度来说,运行库(runtime)可以理解为执行给定编译代码单元所需的外部服务的集合。比如,当Java程序员向一台新电脑部署软件时,要确保软件运行,电脑上就要安装JVM(Java Virtual Machine,Java虚拟机)。

      .NET平台提供了另一种运行库系统。.NET运行库与刚才提到的其他运行库的关键不同在于,.NET运行库提供了一个定义明确的运行库层,可以被支持.NET的所有语言和平台所共享。

      CLR中最重要的部分是由名为mscoree.dll的库(又称公共对象运行库执行引擎)物理表示的。当用户程序引用一个程序集,要使用它时,mscoree.dll将首先自动加载,然后由它负责将需要的程序集导入内存。运行时引擎负责许多任务,首要的任务是负责解析程序集的位置,并通过读取其中包含的元数据,在二进制文件中发现所请求的类型。接着,CLR在内存中为类型布局,将关联的CIL编译成特定平台的指令,执行所有需要的安全检查,然后运行当前的代码。

      除了导入自定义的程序集和建立自定义的类型,必要时CLR也会与包含在.NET基础类库的类型交互。虽然完整的基础类库被分为若干分离的程序集,但最重要的程序集是mscorlib.dll。mscorlib.dll包含大量核心类型,它们封装了各种常见的编程任务与.NET语言用到的核心数据类型。当建立一个.NET解决方案时,你可以自动访问这些程序集。

      图1-4说明了发生在源代码(它是用来许多基础类库类型)、.NET编译器和.NET执行引擎之间的工作流。

    图1-1 mscoree.dll工作流

  • 相关阅读:
    HDU Railroad (记忆化)
    HDU 1227 Fast Food
    HDU 3008 Warcraft
    asp vbscript 检测客户端浏览器和操作系统(也可以易于升级到ASP.NET)
    Csharp 讀取大文本文件數據到DataTable中,大批量插入到數據庫中
    csharp 在万年历中计算显示农历日子出错
    csharp create ICS file extension
    CSS DIV Shadow
    DataTable search keyword
    User select fontface/color/size/backgroundColor设置 字体,颜色,大小,背景色兼容主流浏览器
  • 原文地址:https://www.cnblogs.com/gyt-xtt/p/6425264.html
Copyright © 2011-2022 走看看