数据类型

在C#语言中,符合公共语言规范的数据类型可以分为两大类:值类型和引用类型。

值类型直接存储值,而引用类型存储的是对值的引用。

值类型

值类型包括简单值类型和复合值类型。

简单值类型

值类型直接存储值,它与引用类型不同,从值类型不可能派生出新的类型。

值类型包括简单值类型和复合值类型。

简单值类型可细分为整数类型、字符类型、实数类型和布尔类型。

复合值类型则是简单值类型的复合,包括结构类型和枚举类型。

整数类型

C#中共定义了8种整数类型:字节型(sbyte)、无符号字节型(byte)、短整型(short)、无符号短整型(ushort)、整形(int)、无符号整形(uint)、长整型(long)、无符号长整型(ulong),其划分的依据是该类型的变量在内存中占得位数。

C#中的每个整形类型都对应以.NET类库中定义的一个结构,这些结构在程序集System中定义。例如:整形int所对应的结构是System.Int32,在程序中每定义一个int类型的变量,实际上就创建了System.Int32结构的一个实例。

上述结构都提供了两个静态属性:MinValue(最小值)和MaxValue(最大值)。

字符类型

字符是计算机文字信息处理的基本单位,它包括单个汉字、单个字母、数字、标点符号以及特殊的控制符号。不同的字符集包含的字符数量和字符的表示方式各不相同,C#中采用是Unicode字符集,其中一个字符长度为16位。

C#中的字符类型(char)实际上对应的是.NET类库中的结构System.Char,表示字符时要注意用单引号把字符括起来。

在各种标点符号中反斜杠“\”在C#中有着特殊的含义,用来引导各种转义符,即通过反斜杠“\”加其他常规字符来表示一些特殊字符,以避免表达上的困难。

实数类型

C#中提供了3中实数类型:单精度类型(float)、双精度类型(double)和十进制小数类型(decimal)。

采用默认的小数格式书写的实数是double类型。要声明float和decimal类型,还需要在小数后面加上后缀f和m(不区分大小写)。

例如:double x=1.2;  float y=1.2f;   decimal z=1.2m;

C#中的float、 double和decimal类型分别对应于.NET类库中的System.Single、System.Double和System.Decimal结构。

上述三种结构都提供了五种基本静态属性:MinValue、MaxValue、NaN、PositiveInfinity和NegativeInfinity分别表示:取值范围的最大值、最小值、非数值、正无穷大、负无穷大。

布尔类型

布尔类型(bool)表示布尔逻辑量,取值只能是true或者false,分别表示“真”和“假”这两个概念。

C#中的bool类型对应于.NET类库中的System.Boolean结构。

结构

把一系列相关的信息组织成为一个单一实体的过程,就是创建一个结构的过程。

结构类型采用关键字struct进行定义,其中可以包含零个或任意多个成员。

结构类型包含的成员类型没有限制,可以是简单值类型,也可以是结构类型和枚举类型,还可以是各种引用类型。

结构中能为静态字段赋值,但不能为非静态字段(即实例字段)赋值。

结构类型格式:

[访问修饰符]  struct  结构名

{

   结构成员;

}

枚举

枚举类型是一种独特复合值类型,它从System.Enum继承而来,使用关键字enum来定义,主要用于表示一组逻辑上相关的项的组合。枚举的意思就在于限定变量的取值范围。

枚举的基础类型只能是整数类型,如果没有显示声明基础类型,则默认是Int32。枚举成员的取值必须和枚举声明的基础类型相同,并且必须在类型的范围之内。

例如:

enum Weekday

{

Sunday=1,Monday=2,Tuesday=3,

Wednesday=4,Thrsday=5,Friday=6,Saturday=7

}

其中,1,2……为枚举的取值。

枚举成员的访问权限隐含为public。

枚举类型格式:

[访问修饰符]  enum  枚举名 [:基础类型]

{

   枚举成员,………

}

1>.基础类型必须能够表示该枚举中定义的所有枚举数值。枚举声明可以显式地声明 byte、sbyte、short、ushort、int、uint、long 或 ulong 类型作为对应的基础类型。没有显式地声明基础类型的枚举声明意味着所对应的基础类型是int。

2>.枚举中的枚举成员不能是数字,不能以数字开头,可以是中文或英文,且没有数据类型的表示。任意两个枚举成员不能具有相同的名称。每个枚举成员均具有相关联的常数值,此值的类型就是枚举的基础类型,每个枚举成员的常数值必须在该枚举的基础类型的范围之内。示例: public enum TimeofDay:uint { Morning=-3, Afternoon=-2, Evening=-1 } 产生编译时错误,原因是常数值 -1、-2 和 –3 不在基础整型uint的范围内。如果不指定,那么C#编译器默认枚举中的第一个枚举成员对应的整数为0,其后每个枚举成员的值依次递增1。也可以在定义时直接指定枚举成员的整数值。

3>.枚举的枚举成员支持加减操作。

程序中使用枚举时,通常有以下限制:

1.不能定义自己的方法

2.不能实现接口

3.不能定义属性或事件

结构与枚举的比较:

结构类型是由一组不同类型的成员所组成的新的数据类型,结构类型的变量包含了所有成员的值。

枚举类型只是列举出各个成员,枚举类型的变量在某一时刻只能取其中某个成员的值。且对枚举成员的访问不是通过枚举类型的变量,而是通过枚举类型的名称。

 

引用类型

引用类型包括类(class)、数组(array)、接口(interface)、委托(delegate)。

在C#中,类(class)是一种最基本的类型。而程序所实现的功能也主要由类及其成员来提供。C#中不允许使用全局类型,如全局字段、全局方法等,只有将这些类型都定义为某个类的成员才是合法的。

类是一组具有相同数据结构和相同操作的对象的集合,是对一系列具有相同性质的对象的抽象,是对对象共同特征的描述。

定义类的语法:

[访问修饰符]  class  <类名>

{

  类的主体;//成员字段、成员方法

}

类提供的各种功能都要通过其成员来实现。类中的成员分为三类:数据成员、函数成员和嵌套成员。在类中不允许有任何两个标识相同的成员,即使它们是不同的成员类型。

数据成员-字段

字段表示类的固有数据成员,他可以是值类型或引用类型;可以是系统预定义的类型或用户自己定义的类型。

字段的名称是对类中字段的唯一标识。类中定义一个字段时,这个字段并没有获得实际的值和存储空间,只有在对象实例化之后,才会拥有一个值,并被分配到属于自己的存储空间。

如果既没有在类中为字段定义值,也没有在类的实例中为字段赋值,这时候字段会被赋予其类型的默认值。对于所有的整数类型、实数类型、字符类型和枚举类型,其默认值为0;对于布尔类型,其默认值为False;而对于所有的引用类型,其默认值为null。

函数成员
方法

方法是最基本的函数成员,用于表示类所能执行的计算和操作。

声明一个方法是,需要依次指定返回类型、方法名、参数列表和方法的执行体。参数列表包含在一对小括号中,如果有多个参数,则相互之间用逗号分隔。方法的执行体为一对大括号括起来的代码。

1>.定义语法:

[访问修饰符] 返回值类型 <方法名> ([参数列表])

{

  //执行体

}

注意:

1.方法的声明中,只有参数列表可以为空,其他3项则不可缺少。

2.返回类型:如没有返回值,那么返回类型应为void。如果有返回值,写上返回值的数据类型,在方法执行体中必须用Return返回同一数据类型的值。

2>.参数列表:

C#中的方法可以接受的参数类型共有4种:

(1).普通参数:无需特别定义。包括(值类型-值传递、引用类型-值传递)

值传递,传递的是栈内存中的内容,即在栈内存中开辟了一块新的内存空间,并将原先栈内存中的内容拷贝了一个副本给参数

(2).引用型参数:以关键字ref定义,采用引用传递。包括(值类型-引用传递、引用类型-引用传递)

引用传递,传递的是栈本身的地址,即栈内存中并没有开辟新的内存空间,只是把新变量的指针指向原先栈的地址。

(3).输出型参数:以关键字out定义,采用引用传递,其实参可以不进行初始化。

数组型参数:

一:当数组型参数没有以关键字params定义时,传递给数组型参数的实参只能是数组变量,且方法参数可以定义多个数组参数,数组参数可以放在方法参数的任何位置,数组参数可以是多维数组;二:当数组型参数以关键字params定义时,传递给方法的实参数个数是可以动态改变的,且传递给数组型参数的实参可以是一个数组变量,也可以是多个数组元素变量。当实参是数组变量时,采用引用传递;当实参是数组元素变量时,采用值传递。

参数的注意事项:

在使用引用型参数和输出型参数时,关键字ref和out不仅要在方法定义时指明,而且在方法调用时同样需要写出。

输出型参数的作用:执行方法之后返回传递的参数的结果。

输出型参数的约束:在定义的方法体中,要对输出型参数进行初始化;在调用方法时传递的输出型参数必须为变量(调用时不需要初始化,而且初始化也没用)。

数组型参数的使用的规定(特定于用params修饰):1.方法中只允许定义一个数组型参数,而且该参数必须位于参数列表中的最后。2.数组型参数所定义的数组必须是一维数组。3.数组型参数不能同时既为引用型参数又为输出型参数。4. params可变参数可以传递也可以不传递参数,如果不传递参数,则args数组为一个长度为0的数组。例如:

Test(string msg,params int[] args)

Test("XXX");       args,为一个长度为0的数组

Test("XXX",null);  args,为null

3>.方法重载:

在同一个类中不允许有标识相同的成员,对于方法来说,方法名和参数列表共同组成方法的标识。因此在一个类中允许存在两个相同名称的方法,只要方法的参数列表不完全相同(参数数量或参数类型不同),这时称该方法具有同名的重载形式,即方法名相同而标识不同。

注:方法重装不支持在ref和out之间的重载,例如,

public void Method(string msg){}            --1

public void Method(ref string msg){}        --2

public void Method(out string msg){msg="";} --3

1和2是方法重装、1和3也是方法重装、但2和3不是方法重装。 

构造函数

1>.实例构造函数

构造函数的作用:用于对类的数据成员进行初始化工作。构造函数是一种特殊的函数成员,它在每次创建对象时被自动调用。

构造函数的语法:

[访问修饰符]  类名([参数列表])

{

  构造函数的主体

}

使用构造函数要注意的问题:

1.构造函数通常是公有的(使用public修饰符声明),如果声明为保护的(protected)或私有的(private),则该构造函数不能用于类的实例化。和一般方法不同,不加访问限制修饰符的构造函数默认是共有的。构造函数不声明返回值类型,但可以带参数也可以不带参数。构造函数的名称要与类名相同。

2.不带任何参数的构造函数称为“默认构造函数”。如果只定义了带参数的构造函数,则在创建对象时必须指定相应的参数。如果在类中没有显示的定义一个构造函数,编译器也会为其生成一个默认的构造函数,其执行代码为空,在任何时候使用new关键字来创建对象时,都会调用该构造函数。

3.构造函数的代码中通常只进行对象的初始化工作,而不应执行其他操作。

4.类的构造函数样式决定了类的对象的声明的样式。

5.构造函数支持重载。

注意:

构造函数不能被继承的。

当一个子类继承父类以后,该子类中的所有构造函数默认情况下,在自己被调用之前都会调用一次父类的无参数的构造函数,如果此时父类中没有无参数的构造函数,则报错。解决办法,在子类的构造函数后面通过base()的方式,明确指定要调用父类中的那个构造函数。

2>.静态构造函数

静态构造函数的作用:静态构造函数用于对静态字段、只读字段等进行初始化,或用于执行仅需执行一次的特定操作。静态构造函数的典型用途是:当类使用日志文件时,将使用这种构造函数向日志文件中写入项。静态构造函数在为非托管代码创建包装类时也很有用,此时该构造函数可以调用 LoadLibrary 方法。

静态函数的特点:1.类的静态构造函数在给定应用程序域中至多执行一次,在创建类的第一个实例或引用任何静态成员之前,将自动调用静态构造函数来初始化类。2.静态构造函数是不可继承的,而且不能被直接调用。

静态构造函数语法:

static  类名( )

{

  静态构造函数的主体

}

定义静态构造函数时应注意:静态构造函数不能有访问修饰符,也不能有参数,因为静态函数是私有的。

属性器

为了实现良好的数据封装和数据隐藏,C#为类提供了属性成员。属性是对字段的扩展,它通过属性访问函数来控制对字段的读写。属性访问函数包括get访问函数和set访问函数,分别用于对字段的读取和修改。

属性语法:

[访问修饰符]  数据类型  属性器名

{

  get{return  字段名;}

  set{字段名=value;}

}

通过反编译工具可以看到,编译器会把属性器的get、set生成为相对应的get()、set(数据类型 value)。

如果使用缺省的属性器、即例如:public string Name{get;set;},编译器会自动为此属性器生成一个私有字段来存放属性器操作的值。

注:1.无论是get访问函数的返回值,还是传递给set访问函数的value参数值,其类型都应与属性所声明的数据类型保持一致。 2.属性可以作为特殊的方法来使用,而不必和字段一一对应,在属性的访问函数中可以进行各种控制和计算。3.属性和字段最大的区别在于属性并不存储变量的值。4.属性可以被声明为静态的。

索引函数

索引函数是对属性的进一步扩展,它能够以数组的方式来控制对多个字段的读写访问。索引函数被看作是get和set访问函数的组合体,使用return语句为get访问函数返回结果,使用value关键字为set访问函数传递值,与属性器不同之处在于:

1.索引函数以this关键字加数组下标[]进行定义,并通过数组下标的形式进行访问。

2.索引函数的get访问函数和set访问函数带有参数(通常为整数类型或字符串类型)。

3.索引函数不能为静态的。

4.索引函数所维护的对象可以是连续的数组,也可以是多个离散的字段。

索引实例:https://files.cnblogs.com/zyu19890106/%E7%B4%A2%E5%BC%95%E5%AE%9E%E4%BE%8B.rar

静态成员

C#中通过关键字static来定义静态成员。

静态成员,成员属于类型本身所有。非静态成员也叫实例成员,成员属于类型的实例所有。这里所说的静态的含义是:成员不会随着具体对象的变化而变化。

静态成员通过类调用,而实例成员通过对象调用。

对于类的静态字段属于类所有,为这个类的所有实例所共享,无论这个类创建了多少个对象,一个静态字段在内存中只占有一块区域;而对于实例字段,每创建一个类的实例,就在内存中开辟一块区域用于存储该字段。

静态方法的执行代码只能直接使用静态成员,而使用非静态成员时需要通过类型的实例进行。但是非静态方法的执行代码可以直接调用静态和非静态成员。

静态类中的所有成员都必须是静态的。

Main方法

Main方法是应用程序的入口,每个C#可执行程序都必须有一个执行入口。

Main方法定义时需要有static修饰符,且返回类型必须是void或int,而方法的参数要么为空,要么为string[]类型。

数组

数组主要用于对同一类型的数据进行批量处理。它包含多个数据对象,这些数据对象叫做“数组元素”。数组对象被定义为存储数组元素类型值的一系列位置,也就是说,数组是一个存储一系列元素的对象。数组中存储位置的数量由数组的维数和每维度的上下限确定。

数组类型是从抽象基类型Array派生的引用类型。

数组是包含若干相同类型的变量,数组中的变量称为数组元素。数组能够容纳元素的数量称为数组的长度(可使用Length属性或GetLength方法获得),数组有其维数即数组的秩(使用Rank属性获得)。数组中的每一个元素都具有唯一的索引与其相对应,数组的索引从零开始(使用GetValue方法或索引函数[]可以访问指定数组元素)。

一个数组的定义包含以下几个要素:

1.元素类型

2.数组的维数

3.每个维数的上下线

声明数组语法:

一维数组:数据类型[]  数组名称;

二维数组:数据类型[,]  数组名称;

注意:数组的类型可以是基础类型,也可以是枚举或其他类型,数组的长度不是声明的一部分。

在访问数组前,必须对数组初始化。数组的初始化有很多形式。

1.可以通过new运算符创建数组并将数组元素初始化为他们的默认值,例如:int[]arr=new int[5];。

2.可以在声明数组时将其初始化,并且初始化的值为用户自定义的值,例如:

int[]arr=new int[5]{12,32,100,45,78};或

int[]arr=new int[]{12,32,100,45,78};在这种中编译器将根据初始值的数量来计算数组长度。

3.可以声明一个数组变量时不对其初始化,但在对数组初始化时必须使用new运算符,例如:

int[]arr;

arr=new int[5]{12,32,100,45,78};

4.初始化数组时可以省略new运算符和数组的长度,编译器将根据初始化值的数量来计算数组长度,并创建数组,例如:

int[]arr={12,32,100,45,78};

当数组元素的类型为值类型时,数据直接存放在数组中,而当数组元素的类型为引用类型时,数组中存放的只是各个引用对象的地址。

如果数组元素为引用类型,那么在初始化整个数组之后,还要初始化各个数组元素。此时不排除多个数组元素指向同一个对象的可能,那么修改其中的一个数组元素将会影响到其他元素。

多维数组

多维数组的数组元素本身也是数组,它又可以分为规则多维数组和不规则多维数组。

对于规则多维数组,数组元素连续存放,各个数组元素自身的长度相等,定义时通过中括号([])中的逗号来划分数组的维数,如:

int[,] arr1={{0,0,1,2},{2,3,6,8},{21,0,45,2}};

{0,0,1,2},{2,3,6,8},{21,0,45,2}是arr1的数组元素。

对于不规则多维数组,可以将它理解为广义上的一维数组,其每个数组元素又是一个子数组,而且这些子数组的长度可以不相同。不规则多维数组的定义需要使用多个中括号,而且对数组进行初始化之后不能忘记对各个子数组进行初始化,在不规则多维数组中存储的只是指向各个数组的地址,即数组中的元素完全是以引用对象的形式存在的。

对不规则数组的定义,如:

int[][] arr2=new int[3][];

arr2[0]=new int[4];

arr2[1]=new int[5];

arr2[2]=new int[2];

接口

接口就是一个协议,是对一组能够提供相同服务的类的抽象。

接口的作用:

1.接口用于描述一组类的公共方法/公共属性。它不实现任何的方法或属性,只是告诉继承它的类至少要实现哪些功能,继承它的类可以增加自己的方法。

2.使用接口可以使继承它的类: 命名统一、规范,易于维护。

3.提供永远的接口。 当类增加时,现有接口方法能够满足继承类中的大多数方法,没必要重新给新类设计一组方法,提高了开发效率。

接口是一种抽象的数据类型,它不能像其他引用类型那样被实例化。接口定义了服务,但并不提供服务的实现方式。如果某个类继承了一个接口,它就需要实现该接口所定义的所有服务,接口之间也存在继承关系。如果一个类同时继承了接口和其他类,定义时应将基类写在前面,接口写在后面。

接口通过关键字interface来定义,其所能提供的服务用方法来描述。

[访问修饰符]  interface  <接口名>

{      //声明主体    }

声明接口是需要注意的事项:

1.接口主体只限对方法、事件、索引器以及属性的声明。接口中不能包含字段、构造函数和常量等。

2.接口成员是隐式公开的,如果对其显示指定访问级别,就会出现编译错误。

3.在接口中不能实现任何方法、事件、或者索引器。在指定方法时,只需给出返回类型、名称和参数列表,然后以分号结束。

4.接口名称需始终冠以大写字母“I”。

注意:

(1).如果多个接口定义了相同的方法成员,而某个类又同时继承了这些接口,那么在派生类中可以用一个方法来加以实现。如果希望加以区分的话,那么就要在方法前面加上接口声明,此时方法的定义中则不能包含访问限制修饰符。

(2).显示实现接口,不能加访问修饰符,默认是私有的。显示实现接口,在方法名称前加“接口名”,形如:接口名.方法名。显示实现接口,只能通过接口变量来调用。

1>.IDisposable接口

当一个类中需要调用非托管资源,要实现IDisposable接口,把释放非托管资源的代码写在Dispose函数中。

using(对象){}:会自动调用“对象.Dispose()”

2>.IEnumerable接口

可枚举的,其中只有一个方法,即GetEnumerator(),用于得到枚举器。

3>.IEnumerator接口

枚举器接口

委托

委托是一种数据类型使用delegate定义,像类一样(可以声明委托类型变量)。

委托是用来存储方法的。

委托的作用:

把函数内变化的部分封装起来,提高函数的扩展性。

委托的使用:

分为3步:定义、实例化、和调用。

1.委托通过关键字delegate定义.

格式:[修饰符] delegate  返回值数据类型  委托名([参数列表]);

2.委托的实例化使用关键字new进行,同时需要指定所引用的方法,而且方法的返回类型和参数列表都应和定义的委托相一致。

3.可以像调用方法那样调用委托,只不过此时无需在指定所属的对象或类。

示例:https://files.cnblogs.com/zyu19890106/%E5%A7%94%E6%89%98.rar

事件(类成员,委托对象)

事件是类的一种特殊成员。类的事件成员是某个委托的实例,而类的其他函数成员(如方法、属性访问函数等)可以引发该事件。

对象的事件用于对外界发生的特定情况做出响应,开发人员在使用该对象时,可将特定的事件处理方法与事件相关联,那么在事件被引发时,委托对象(即事件)就会调用事件处理方法中的代码。

事件的语法格式:

[访问修饰符]  event  委托类型名  事件名;

事件具有以下特点:

1.发行者(即含有事件的类)确定何时引发事件,即事件必须由类的内部成员来触发,订户(事件的处理方法的类)确定执行何种操作来响应该事件。

2.没有订户的事件永远也不会引发。

3.一个事件可以有多个订户,一个订户可处理来自多个发行者的多个事件。

EventHandler委托对象

System程序集中一个定义了名为EventHandler的委托对象,其原型为:

Public  delegate  void EventHandler(object sender,EventArgs e);

其中参数sender表示引发事件的对象,即包含该事件的对象,参数e表示事件中包含的数据,其类型EventArgs也是System程序集中的一个类。除非有特殊需要,C#建议尽量使用EventHandler或其派生类作为事件类型。如果还需要处理特定的事件数据,那么开发人员可以定义EventArgs的派生类,并将数据包含在事件参数中。

实例:https://files.cnblogs.com/zyu19890106/%E4%BA%8B%E4%BB%B6.rar

操作符重载

定义:使用关键字operator,后跟要重载的操作符。

在C#中允许被重载的操作符包括:

一元操作符:+、-、!、~、++、--、(T)、true、false

二元操作符:+、-、*、/、%、&、|、^、<<、>>、==、!=、>、<、>=、<=

考虑到操作符的对称性,下列操作符要求被成对重载,即不能只重载其中的一个,一元操作符:true和false,二元操作符:==和!=;>和<;>=和<=。

关键字true和false可以作为操作符来重载,此时返回类型必须是bool。

对于所有的复合赋值操作符,只要其左部操作符是可重载的二元操作符,并且操作符重载的返回类型可以隐式地转换为当前类型,那么相应的赋值操作符也被隐式重载。(例如,二元操作符:+被重载,并且重载方法的返回类型可以隐式地转换为当前类型,则赋值操作符+=也被隐式重载了)

对于类型转换操作符(T),在定义重载时需要为T指定一个数据类型。类型转换操作符的重载较为特殊:它不显示地定义返回类型,而认为操作符的返回类型始终为T所代表的类型;此外,它需要用关键字explicit或implicit来指明转换是显式的还是隐式的。

注:被重载的操作符也是一种特殊的方法,且必须被声明为公有和静态的。重载一元操作符时需提供一个参数,且参数类型应为当前类型,或者是可以隐式转换为当前类型;重载二元操作符时需提供两个参数,且至少有一个参数类型为当前类型,或者可以隐式转换为当前类型。

操作符重载.rar:
https://files.cnblogs.com/zyu19890106/%E6%93%8D%E4%BD%9C%E7%AC%A6%E9%87%8D%E8%BD%BD.rar 

类型装换

C#语言可以在一些规定数据类型之间进行转换,其中包括数值(字符)转换、枚举转换、引用转换、以及装箱和拆箱转换。从转换的声明方式来看,每种转换又可以分为隐式转换和显式转换。隐式转换就是系统默认的、不需要加以声明就可以直接进行的转换;而显式转换又叫强制类型转换,它需要明确指定转换的类型。

注:只有在内存存储上存在交集的类型之间才能进行类型转换,否则不可以。

数值转换

数值转换时指在各种整数、实数以及字符类型之间进行的转换。

数值转换有一个原则,即从低精度类型到高精度类型通常可以进行隐式转换;而从高精度类型到低精度类型则必须进行显式转换;从精度相同的无符号数值类型向有符号数值类型的转换也只能是显式的转换。

Char类型与ushort类型存在一一对应的关系。在将char类型的变量转换为ushort类型时,将得到该字符的十进制整数编码;特别地,如果字符位于

ASCⅡ编码范围内,那么将的到0—255之间的ASCⅡ编码。

任何数值类型的变量要转换到char类型,都必须使用显式转换。

枚举转换

除了可以把0这个值直接赋予枚举类型的变量以外,不存在枚举类型与其他任何类型之间的隐式转换。

而和枚举类型相关的显式转换包括如下内容:

1.从所有整数类型(包括字符类型)和实数类型到枚举类型的显式转换。

2.从枚举类型到所有整数类型(包括字符类型)和实数类型的显式转换。

3.从枚举类型到枚举类型的显式转换。

引用转换

引用转换包括类之间、类与接口之间、接口之间、委托之间、以及数组之间的类型转换。由于委托和数组分别是由类System .Delegate和System.Array派生的,因此可以将所有的引用转换都视为类之间,以及类与接口之间的转换。

由于引用类型的变量只是保存对目标对象的引用,因此任何引用转换都不会修改对象的内容,也就不会有信息丢失。

1.隐式引用转换

隐式引用转换的基本规则是:设有A和B两种引用类型,不论它们是类、接口,或是由类所扩展的委托、数组,只要B从A中继承,那么就存在从B到A的隐式转换。而从数组A1(派生)向数组A2(基)之间的隐式转换还有下列特定的要求:①A1和A2维数相同。②A1和A2的数组元素都是引用类型。③存在着从A1数组元素类型向A2数组元素类型的隐式引用转换。最后,空引用值null可以赋值给任何一种引用类型的变量。

2.显示引用转换

任何从基类向派生类型的转换(包括类之间、接口之间、以及类和接口之间的转换)都要求使用显示转换。此外,从数字A1向数组A2之间的显示转换还用下列特定的要求: ①A1和A2维数相同。②A1和A2的数组元素都是引用类型。③存在着从A1数组元素类型向A2数组元素类型的显式引用转换。显示引用转换在编译是被编译器忽略,而在运行时有.NET  CLR执行检查,如果转换失败,程序将抛出一个System.InvalidCastException异常。

装箱和拆箱

在值类型和引用类型之间相互转换就是装箱和拆箱装换。

装箱转换

装箱转换是从值类型到引用类型的隐式转换,包括从任何值类型到System.Object类型的转换,以及从某个值类型到它所实现的接口类型的转换。

拆箱转换

拆箱转换是从引用类型到值类型的显示转换,包括从System.Object类型到任何值类型的转换,以及从某个接口到继承该接口的某个值类型的转换。

其他转换

数字转换为字符串

ToString()

字符串转换为数值类型

1.Parse

用法:数值类型.Parse(“可转换的字符串常量或变量");

2.Convert

用法:Convert.ToInt32(“可转换的字符串常量或变量”);

Convert. ToInt32()和int.parse()的区别

对null值的处理方法,Convert.ToInt32(null)会返回0而不会产生任何异常;但int.Parse(null)则会产生异常。

对double类型值得处理方法,Convert. ToInt32(double value)会根据value的值不同返回不同的结果,当value的小数部分大于0.5时进位,当value的小数部分小于0.5时舍去,当value的小数部分为0.5时则返回二者中的偶数(例如为4.5将转换为4,而5.5转换为6);int.Parse(double value)直接报错。

类型推断

1.使用var声明变量与直接使用对应的类型声明变量是完全一样的,编译器在编译时就会将var替换成了对应的数据类型。

var只能用做局部变量。用var定义的时候必须给var赋值,否则无法进行类型推断。例如:

int n = 100;

var m = 100;

n与m是完全一样的

2.C#中的var与js中的var完全不一样。C#中的var依然表示强类型,而js中的var是弱类型。

弱引用

弱引用的意思:重新创建对象是非常耗时的;把对象弱引用起来(弱引用的变量,是可以被垃圾回收的),当下次使用时,如果该对象还没有被垃圾回收就可以直接使用了,否则需要重新创建变量。

弱引用实例.rar:
https://files.cnblogs.com/zyu19890106/%E5%BC%B1%E5%BC%95%E7%94%A8%E5%AE%9E%E4%BE%8B.rar

 

posted @ 2014-08-20 23:00  百年一人  阅读(412)  评论(0编辑  收藏  举报