第十六章 转换
- 值类型转换:值类型的转换有显示转换和隐式转换,低字节往高字节转换为隐式转换,不存在数据丢失情况,反过来显示转换有可能存在数据丢失,引发异常,可以使用checked和unchecked进行溢出检测上下文,如果有数据丢失,checked会抛出异常,当然它们不仅仅可以检测表达式,也可以检测整块代码是否存在异常。
- 引用转换:引用类型包括引用和数据两部分,引用部分用来说明数据类型,引用转换接受源引用并返回一个指向堆中同一位置的新引用,且被标记为其他类型。
class A
{public int f1;}
class B:A
{public int f2;}
B b = new B();
A a = (A)b; //其实可以隐式转换
Console.WriteLine("{0}",b.f1); //没有问题
Console.WriteLine("{0}",a.f2); //表面上是a的对象,实际上是指向B类型的对象,但是无法访问B扩展的方法,编译出错。
- 隐式引用转换:所有引用类型都可以隐式转换为object类型;任何类型都可以隐式转换到它继承的接口;类可以隐式转换到继承链上的任何类以及它实现的任何接口;委托可以隐式转换到.NET BCL类和接口;数组隐式转换要求两个数组具有相同的维度以及数组元素都是引用类型。
- 显示引用转换:从一个普通类型到一个更精确类型的引用转换,包括从object到任何类型以及从基类到继承类的转换,一般而言,这种转换不安全会出现异常。
- 装箱转换:**装箱转换是一种隐式转换,它接受一个值类型的值,根据这个值在堆上创建一个完整的引用类型对象并返回对象引用。**注意,它返回的是值的引用类型的副本,装箱之后,该值产生两个副本,原始值类型和引用类型副本,存储在不同的内存空间,每一个都可以独立操作。
int i = 12;
object obj = i;
Console.WriteLine("i={0},obj = {1}",i,obj);
i = 16;
obj = 18;
Console.WriteLine("i = {0},obj = {1}",i,obj);
执行结果:
- 拆箱转换:可以认为是装箱转换的逆过程,怎么装箱,就怎么拆箱。注意只能拆成装箱前的类型,而不能是其他类型。
int i1 = 16;
object obj1 =i1; //装箱
int j1 = (int)obj1; //拆箱
Console.WriteLine("i1 = {0},obj1 = {1},j1 = {2}",i1,obj1,j1);
结果是:
- 用户自定义转换:它也有隐式转换和显式转换,要注意格式,(这个像之前重写运算符的那样)
public static implicit/explicit operator TargetType(SourceType Identifier)
{
return ObjectOfTargetType;
}
example:
public static implicit operator int(Myclass myc) //用户自定义隐式转换
{
return myc.age;
}
- 用户自定义转换的一些约束:只能在类或结构中定义用户自定义转换;无需重复定义标准隐式转换和显示转换;源类型和目标类型必须不同;源类型和目标类型不能存在继承关系;源类型不能是接口类型或者object类型;转换运算符必须是源类型或目标类型的成员;如果具有相同的源类型和目标类型,不能声明显式转换和隐式转换。
- 示例:
class Person
{
public string Name;
public int Age;
public Person(string name,int age)
{
Name = name;
Age = age;
}
public static implicit operator int(Person p)
{
return p.Age;
}
public static implicit operator Person(int i)
{
return new Person("Nemo",i);
}
class Program
{
static void Main()
{
Person bill = new Person("bill",25);
int age = bill;
Console.WriteLine("Person Info:{0},{1}",bill.Name,age);
Person anon = 35;
Console.WriteLine("Person Info:{0},{1}",anon.Name,anon.Age);
}
}
执行结果:
- 多步用户自定义转换:
class Employee :Person{}
class Person
{
public string Name;
public int Age;
public static implicit operator int(Person p)
{
return p.Age;
}
}
class Program
{
static void Main()
{
Employee bill = new Employee();
bill.Name = "William";
bill.Age = 25;
float svar = bill;
Console.WriteLine("Person Info:{0},{1}",bill.Name,svar);
}
}
执行结果:Person Info:William,25