CTS通用类型系统,是.Net中一套定义类型的规则。我们要掌握c#开发,首先要建立这个类型概念,只有知道c#的元素是什么类型,才能进行相关的分析和选材。

一、值类型和引用类型

C#分两个大类,一类是引用类型;另一类是值类型。

引用类型从技术上来讲,就是一个指针,指向具体的数据;而值类型实际就存放数据。因此引用类型大小都是固定的(虽然它实际关联其他部分,但是你传递引用类型不需要传递这些,只需要传递指针),而值类型有不同的大小。

所有类型都从System.Object派生,包括值类型分支。所有值类型都是System.ValueType的子类,或者是枚举System.Enum的子类。而System.ValueType 和System.Enum自身却是引用类型。因此继承关系和是否是值类型无关,用户需要通过class ,struct等关键字去定义不同的类型。

用户自定义的类、接口、数组、委托是引用类型;自定义的枚举、结构是值类型。

结构和类的区别是,结构的基类型不能自定义,固定是System.ValueType,也就是结构设计上,不能建立多层的继承模式。不过结构可以实现接口。

值类型转换到引用类型时,如转化成基类型Object会产生“装箱”操作,从技术上讲,就是将数据复制到新的内存空间,然后用指针指向它,因此是一个耗费资源的操作。对应的”取消装箱”是个相反的过程。

二、特殊类型

泛型不是一种类型,而是一种定义类型的快捷方式。先用占位符作为类型定义的一部分,在实际定义类型的时候给出对应的部分,形成真实的类型。如class C<T>{} 的C并不是类型,而是未完成的模版,需要给定T 的实际类型,才能得到完整的类型 如: C<int> 这里就定义了一个C<int>类型。泛型可以用来定义引用类型也可以用来定义值类型。

匿名类型是用new {成员a;成员b;} 格式定义的类型,直接继承自Object,成员具有只读性。该类型主要用来处理临时的数据对象。

可null类型,在值类型后增加?表示可null类型。可null类型是System.Nullable<T>泛型结构的实例。主要用在数据库编程。

三、委托类型和接口类型

委托类型从System.Delegate 或 System.MulticastDelegate 派生,属于引用类型。委托类型通过关键字delegate创建,委托类型特殊性在于它主要是用来封装函数的,而结构和类用来封装数据和操作,其中结构偏向数据,而类偏向操作。可见这三种自定义类型,有各自的重点。

委托相当于函数指针,它自身不保存实际的运算过程,而是保持指向函数的指针。这有点类似引用类型的数据关系。可以用函数名初始化委托,也可以创建“匿名方法”或lambda算式实例化委托。

匿名方法通过 delegate{ 语句} 创建,是一种在函数内创建的闭包。所谓闭包是一段代码,但是可以包含宿主函数的局部变量。

lambda 是匿名方法的改进,如 (x,y)=>x+y 可以简洁的描述简单算法。

委托类型和接口类型的共同点是不涉及具体的实现,而关注“形态”,因此都可以做到分离具体实现的目的。其中接口比委托要强大的地方是接口可以定义多个函数形态,而委托只是一个,不过这可能是优势也可能是劣势,比如你可以定义多个委托,链接不同的实例;而用接口的多个函数形态却只能一个实例去实现。

因此,要联通组件,有两个选择:一、对于选择不同算法实现,或者事件通知,用委托最好;二、对于一组关联的操作,对象互操作,用接口最好。

********************************************

值类型主要由两类组成:

结构分为以下几类:

值类型的主要功能

基于值类型的变量直接包含值。将一个值类型变量赋给另一个值类型变量时,将复制包含的值。这与引用类型变量的赋值不同,引用类型变量的赋值只复制对对象的引用,而不复制对象本身。

所有的值类型均隐式派生自 System.ValueType

与引用类型不同,从值类型不可能派生出新的类型。但与引用类型相同的是,结构也可以实现接口。

与引用类型不同,值类型不可能包含 null 值。然而,可空类型功能允许将 null 赋给值类型。

每种值类型均有一个隐式的默认构造函数来初始化该类型的默认值。有关值类型默认值的信息,请参见默认值表

简单类型的主要功能

所有的简单类型(C# 语言的组成部分)均为 .NET Framework 系统类型的别名。例如,intSystem.Int32 的别名。有关完整的别名列表,请参见内置类型表(C# 参考)

编译时计算操作数均为简单类型常数的常数表达式。

可使用文字初始化简单类型。例如,“A”是 char 类型的文字,而 2001 是 int 类型的文字。

初始化值类型

C# 中的局部变量经初始化后方可使用。因此,如果像下面这样声明了一个局部变量而未将其初始化:

int myInt;

那么在将其初始化之前,无法使用此变量。可使用下列语句将其初始化:

myInt = new int();  // Invoke default constructor for int type.

此语句等效于:

myInt = 0;         // Assign an initial value, 0 in this example.

当然,可以像下面这样用同一个语句进行声明和初始化:

int myInt = new int();

- 或 -

int myInt = 0;

使用 new 运算符时,将调用特定类型的默认构造函数并对变量赋以默认值。在上例中,默认构造函数将值 0 赋给了 myInt。有关通过调用默认构造函数所赋的值的更多信息,请参见默认值表

对于用户定义的类型,使用 new 来调用默认构造函数。例如,下列语句调用了 Point 结构的默认构造函数:

Point p = new Point(); // Invoke default constructor for the struct.

此调用后,该结构被认为已被明确赋值;也就是说该结构的所有成员均已初始化为各自的默认值。

有关 new 运算符的更多信息,请参见 new

有关格式化数字类型输出的信息,请参见格式化数值结果表

摘自:https://msdn.microsoft.com/zh-cn/library/s1ax56ch(VS.80).aspx


*******************************************

C# 中有两种类型:引用类型和值类型。引用类型的变量存储对其数据(对象)的引用,而值类型的变量直接包含其数据。对于引用类型,两种变量可引用同一对象;因此,对一个变量执行的操作会影响另一个变量所引用的对象。对于值类型,每个变量都具有其自己的数据副本,对一个变量执行的操作不会影响另一个变量(ref 和 out 参数变量除外,请参见 ref(C# 参考)out 参数修饰符(C# 参考))。

下列关键字用于声明引用类型:

C# 也提供了下列内置引用类型:

摘自:https://msdn.microsoft.com/zh-cn/library/490f96s2.aspx


********************************************************

在 Visual Basic 中,数据类型是基于其类别实现。  根据特定类型的变量存储的是自己的数据还是指向数据的指针,可以对 Visual Basic 数据类型进行分类。  如果它存储的是自己的数据,则它是值类型;如果它保存指向内存中其他位置的数据的指针,则它是引用类型。  

值类型

如果数据类型在它自己的内存分配中存储数据,则该数据类型就是“值类型”  值类型包括:  

  • 所有数字数据类型

  •  BooleanCharDate

  • 所有结构,即使其成员是引用类型

  • 枚举,因为其基础类型总是 SByteShortIntegerLongByteUShortUIntegerULong

每个结构是值类型,因此,即使它包含引用类型成员。  因此,值类型 (如 CharInteger 由 .NET framework 结构实现。  

可以通过使用保留关键字(例如 Decimal)声明值类型。  也可以使用 New 关键字初始化值类型。  这对于值类型有一个带参数的构造函数的情况尤为有用。  此示例有 Decimal(Int32,Int32,Int32,Boolean,Byte) 构造函数,它从提供的部分生成新的 Decimal 值。  

引用类型

 “引用类型”包含指向存储数据的其他内存位置的指针。  引用类型包括:  

  •              String            

  • 所有数组,即使其元素是值类型

  • 类类型,如 Form

  • 委托

类是一种“引用类型”。  因此,诸如 ObjectString 之类的引用类型都受 .NET Framework 类支持。  请注意,每个数组都是一种引用类型,即使其成员是值类型。  

由于每种引用类型表示基础 .NET framework 类,则必须使用 New 运算符 (Visual Basic) 关键字,在初始化时。  下面的语句初始化一个数组。  

Dim totals() As Single = New Single(8) {}

非类型的元素

以下编程元素未限定为类型,因为您无法将它们中的任何一个指定为声明元素的数据类型:      

  • 命名空间

  • 模块

  • 事件

  • 属性和过程

  • 变量、常数和字段

使用对象数据类型

可以将引用类型或值类型指派给 Object 数据类型的变量。    Object 变量总是存储指向数据的指针,从不存储数据本身。  然而,如果为 Object 变量指派值类型,该变量的行为将如同存储自己的数据一样。  有关更多信息,请参见 Object 数据类型  

可以查看 Object 变量是否通过将为引用类型或值类型到 Microsoft.VisualBasic 命名空间的 Information 类的 IsReference 方法。  如果 Object 变量的内容表示引用类型,则 Information.IsReference 返回 True  


摘自:https://msdn.microsoft.com/zh-cn/library/t63sy5hs.aspx



*******************************************

   一、电脑是由什么来存储所使用的数据?

      这个问题用一句话比较笼统的概括,那就是:电脑使用内存来记忆计算时所使用的数据。

      在现实生活中的数据各种各样,整数、小数、字符串、字符等等,它们都类型是不一样的,所以你要想在计算机中使用这些类型,就必须在内存中为它申请一块合适的空间。

     那有哪些数据类型是C#能使用的呢?我们一起来看一看.

    

      二、基础数据类型有哪些

      首先要了解一点:C#认可的基础数据类型并没有内置于C#语言中,而是内置于.net Framework中。

      如,在c#中声明一个int类型的数据时,声明的实际上是.net结构System.Int32的一个实例。这听起来似乎很深奥,但其意义深远:这表示在语法上,可以把所有的基础数据类型看作是支持某些方法的类。

     类型实际上仍存储为基本类型。基本类型在概念上用.Net结构表示,所以肯定没有性能损失。

     下面大家一起来了解一下C#中定义的内置类型,我们将列出每个类型,以及它们的定义和对应的.net类型(CTS类型)的名称。

      c#有15个预定义类型,其中13个是值类型,两个是引用类型(string 和 object)

 

    1、整型

 

   2、浮点类型

 

    float数据类型用于较小的浮点数,因为它要求的精度较低。

    double数据类型比float数据类型大,提供的精度也大一倍(15位)。

    如果在代码中没有对某个非整数值(如12.3)硬编码,则编译器一般假定该变量是double。

    如果想指定该值为float,可以在其后加上字符F(或f),如:

         float f = 12.3F;

 

 3、decimal类型

 

    decimal类型专门用于进行财务计算,使用decimal类型提供的28位的方式取决于用户。

    要把数字指定为decimal类型,可以在数字的后面加上字符M或(m),如:

    decimal d=12.30M;

 

    4、bool(布尔)类型

 

 

    5、char字符类型

     char类型的字变量是用单引号括起来的。     如'A'

     如果把字符把在"A"(双引号)内,编译器会把它看作是字符串,从而产生错误。

 

    6、引用类型(Object类型和字符串类型)

 

 三、如何声明变量和赋值

   1、变量的定义:是指在程序的运行过程中随时可以发生变化的量

    2、上面我们提到,变量在运行时当中是存在内存当中的,它是一个临时的存放场所。

         那么在内存当中,可以存放如数字、字符串、日期等等各种类型的数据。

 

大家可以看一看这张图,它就把表示内存当中的一个状态。

 

简单的来说,变量就是表示内存当中的一块存储区域。

 

它会对应一个唯一的内存地址,但是我们在使用程序当时候,内存地址不好理解也不好记忆。

那么怎么办呢?

 

在日常生活当中我们都有一个名字,如"张三“、”李四“等,这些名字就是为了便于记忆。

那么同样,在程序当中,为了区别多个变量,那就需要为每个变量赋值一个简短,便于记忆的名字,

这就是变量名

 

     3、 C#中的变量的命名是是有规则的:

         1)、由字母、数字或下划线"_"组成

         2)、必须由字母下划线"_"开头,不能以数字开头

         3)、不能是c#中的关键字 如:int、string、bool、Main、class等 

         4)、区分大小写  如:小写的a  和  大写的A 是两个变量

     

      4、做为一个比较好的学习者,就必须遵守一些变量命名规范:

           1)、变量的名字要有意义,尽量用对应的英语命名,具有“见名知意“的作用。

                  如:姓名   变量取名为 name 或者 用拼单  xingMing,避免用a,b,c来进行命名。

           2)、避免使用单个字符作为变量名( 除在循环里面定的变量)

           3)、当使用多个单词组成变量名时,应该使用骆驼(Camel)命名法

                   骆驼(Camel)命名法:第一个单词的首字母小写,其它单词的首字母大写,如:myName,myAge

           

          选择题:以下变量命名正确的是(     )

                  A、name、 _222*1、 9class、 public

                  B、_teacher、 void、 string、 myName

                  C、$Age、 corss、 fire、 _grade

                  D、_glass、 g23、 c_12、 my_first_2

 

 

      5、变量的声明和赋值

          1)定义变量的语法:

            数据类型    变量名;      (定义一个年龄的变量,年龄是整数,所以变量定义如下:)

              int          age;         [系统会根据数据类型,在内存中分配不同大小的存储空间]

 

             每个数据类型后面,可以定义多个变量,如:(定义姓名、家庭地址、籍贯、民族)

                string name,address,origin,national ;

            

           2)为变量赋值语法:

               =           

              (这里的=号表示赋值运算符,把=号右边的值,赋值给左边的变量名,最后以一个;[分号]结束)


 

 四、变量和常量的区别

         变量:是指在程序的运行过程中随时可以发生变化的量

        常量:是指在程序在运行过程中不会发生变化的变量

         

          常量的特点:

                   1、必须在声明是赋值

                   2、不能在在程序运行时,给常量赋值

                   3、常量是静态的。不必须(实际上,是不允许)在常量声明中包含修饰符static 

        

 五、不同数据类型之间是如何转换的

       在C#中数据类型转换分为两种:1)隐式[又叫自动]类型转换     2)显式[又叫强制]类型转换

           举个简单例子:

           飞机场里面停飞机,这是理所当然,我们把这种叫做隐式[又叫自动]类型转换

   

           那如果我们反过来看一看,飞机里面装飞机场,这个在我们实际生活中,觉得这是根据不可能的,

           但是程序可能做到这一点,我们把这种叫做显式[又叫强制]类型转换

 

       在C#中数据类型转换分为两种:1)隐式[又叫自动]类型转换     2)显式[又叫强制]类型转换

           举个简单例子:

           飞机场里面停飞机,这是理所当然,我们把这种叫做隐式[又叫自动]类型转换

   

           那如果我们反过来看一看,飞机里面装飞机场,这个在我们实际生活中,觉得这是根据不可能的,

           但是程序可以做到这一点,我们把这种叫做显式[又叫强制]类型转换

 

           double和int之间就是(飞机场与飞机)这种关系,我们可以这样理解,double的取值范围比int要大得多

           所以double可以装得下int :

          int a=1234;   

          double b=a;   系统会把a整型变量的值赋值给double变量b.这就是隐式[又叫自动]类型转换

 

         那反过来:

         double a=1234;

         int b=a;        //系统编译时会报错,如图:

         

        

           那如何进行强制转换呢?c#提供了非常简便的方法,如:

          double a=1234;

          int b=(int)a;      //这样就强制把double类型,转换为int类型

 

         最后,再介绍一下,其它数据类型之间的转换(1、字符串转换为其它类型   2、任意类型之间的转换)

         1)、字符串转换为其它类型       

       语法:

        XX.Parse(字符串);         这里的xx代表的如:double,int,bool等

         举个例子来说明一下:

          string strValue="123.45";     //这是一个字符串,时面的值是"123.45"

          现要把它转换成小数类型,就可以使用double.Parse();来进行转换

         double dValue=double.Parse(strValue);

 

       2)、任意类型之间的转换

        语法:     

         Convert.ToXX(任何类型);

 

         如:把一个布尔类型转换为整型

                  bool a = true;
                  int b = Convert.ToInt16(a);
                 Console.WriteLine("转换后的结果是:"+b);  //转换后的结果是:1


备注:摘自:http://www.cnblogs.com/Nobel/archive/2012/12/02/2798503.html

http://www.cnblogs.com/tonney/archive/2011/03/18/1987577.html