一、 类型转换
CLR允许将对象转换为其原来的类型或者它的任何一个基类型。如,在C#中,可以直接将一个对象转换为任何一个基类型;如果要将对象转换为它的任何派生类型,C#要求进行显式转换,因为这种转换可能会失败,因此要求程序员显式的说明确实是要进行这种父类到子类的转换,而不是因为输入错误,如果语句中没有进行这种显示的转换,则会发生编译期错误;当然,如果这个被转换的对象本身确实是父类,那么它是不可能被转换为子类的,即使在语句中进行了显示的转换而通过了编译,但是在运行期间还是会发生运行期错误的。
“将对象转换为其原来的类型”是指一个对象可能在创建时本身是son类型,但是之后被转换为father类型,也就是说,它只是被包装了一层father的外衣,但是实际上它还是son类型,这时如果又将这个对象转换为son类型,就是将这个对象转换为其原来的类型son,这种转换当然是可以成功的。
另外:在第五章第一节中谈到:C#编译器熟悉基元类型,并且会在编译代码时应用自己的规则,所以,一些不同的类型,如Int32和Int64也可以相互进行类型转换,这方面的类型转换规则是:如果在转换过程中,不会造成数据丢失,如Int64类型转换为Int32类型,则可以进行隐式转换;如果转换过程有可能造成数据丢失,如Int32类型转换位Int64类型,Single类型转换位Int16类型,就要求进行显示转换。
例子程序一:
father f = new father();
son s = new son();
father fWraps = s; //子类的对象可以直接转换为父类,好像子类包裹了一层父类的外衣。
son ss = (son)fWraps;//父类的对象转换为子类,必须显示转换,因为这个对象实际上本质是一个子类的对象,因此转换可以成功。
例子程序二:
father f = new father();
son s = (son)f;//将一个父类对象尝试转换为子类对象,虽然进行了显示转换,可以通过编译,但是在运行期间还是会发生错误。
二、 is和as操作符
可以使用is操作符判断一个对象是否与一个类型兼容。
可以使用as操作符简化转型语句,并能提高效率。
例子程序一:
son s = new son();
father fWraps = s;
if( fWraps is son ) //判断对象是否于类型son兼容,判断结果是兼容的。
{
MessageBox.Show( "ok" );
}
例子程序二:
son s = o as son; //将对象o尝试着转换为son类型,如果成功,则s不为null。
if( s!= null )
{
}
三、 命名空间与程序集
命名空间使得我们能够将相关的类型逻辑的组织在一块儿,但是,当不同的命名空间中存在同名的类型,并且程序中又同时引用了这些命名空间时,对这些同名的类型的访问则必须采用完全限定名进行,否则就会产生二义性。
命名空间和程序集并非必然相关,一个命名空间中的各个类型可以分布在不同的程序集中;一个程序集中可以包含多个命名空间的类型。当一个命名空间中的类型分布在不同的程序集中时,如果需要使用所有的命名空间中的类,则需要在项目中将各个程序集文件都加载到项目的引用列表中(项目的引用列表中列出的是所引用的程序集,而不是引用的命名空间,因此会显示出同一个命名空间的不同的各个程序集的名称),之后在项目中就可以无分别的使用这个命名空间中的各个类型而不用管某个特定的类型是存放在哪个程序集中的了,如果各个程序集中定义了同一个命名空间的相同的类型,也就是说重复定义了某个类型,如果在项目中使用了这个类型,那么在编译时会提出警告,并且告知编译器选择使用了哪个程序集中的类型进行编译。
例子程序一 (一个程序集包含多个命名空间的类型):
//WinUI.cs
using System;
namespace WinUI.Query
{
}
namespace WinUI.Report
{
}
//将查询相关的客户端界面类型组织在WinUI.Query命名空间中,将报表相关的客户端界面类型组织在WinUI.Report中,这两个命名空间都存在于程序集WinUI.dll中。