值类型之间的隐式转换关系如下图:
显示转换/强制转换理解示例:
现在我们应该已经知道,占据较少位的值类型可以隐式转换为占据较多位的值类型。
在类型转换时,进行检测结果是否溢出的代码片段称为溢出检测上下文。
checked语句和unchecked语句可以嵌套在任意层次。
引用类型转换接受源引用并返回一个指向同一位置的引用,但是把引用“标记”为其他类型。
委托可以隐式转换为.NET BCL类和接口。
ArrayS数组,其中的元素都是Ts类型,可以隐式转换:
a. .NET BCL类和接口
b. 另一个数组ArrayT,其中元素都是Tt类型(当满足下面所有条件可转换)
i. 两个数组有一样的维度
ii. 元素Ts和元素Tt都是引用类型,而不是值类型
iii. 在元素Ts和Tt之间存在隐式转换
如果将基类强制转换成派生类时,派生类并没有创建对象,就将一个基类对象直接强转为派生类对象,会报InvalidCastException异常(无效强制转换异常)。
第一种情况:派生类转基类,本身是隐式转换,可以但没必要的强制转换。
第二种情况:源引用为null
第三种情况:派生类先转基类,再基类转派生类。(先向上转型,再向下转型)
除了标准转换,我们还可以为类和结构定义隐式或显示转换。
用户自定义转换的约束:
i.S和T必须是不同类型
ii.S和T不能通过继承关联
iii.S和T都不能是接口类型或object类型
iiii.转换运算符必须是S或T的成员
隐式转换代码示例:
internal class Person
{
public string Name;
public int Age;
public Person(string name, int age)
{
Name = name;
Age = age;
}
//将Person隐式转换为int
public static implicit operator int(Person person)
{
return person.Age;
}
//将int类型转换成Person类型
public static implicit operator Person(int i)
{
return new Person("NONE", i);
}
}
internal class Program
{
static void Main(string[] args)
{
Person bill = new Person("Bill", 25);
int age = bill;//将bill隐式转换为int类型
Console.WriteLine("Person Info:{0},{1}",bill.Name,age);
Person person = 17;//将int类型隐式转换为Person类型
Console.WriteLine("Person Info:{0},{1}", person.Name, person.Age);
}
}
显示转换代码示例:
internal class Person
{
public string Name;
public int Age;
public Person(string name, int age)
{
Name = name;
Age = age;
}
//将Person显式转换为int
public static explicit operator int(Person person)
{
return person.Age;
}
//将int类型转换成Person类型
public static explicit operator Person(int i)
{
return new Person("NONE", i);
}
}
internal class Program
{
static void Main(string[] args)
{
Person bill = new Person("Bill", 25);
int age = (int)bill;//将bill显式转换为int类型
Console.WriteLine("Person Info:{0},{1}",bill.Name,age);
Person person =(Person) 17;//将int类型显式转换为Person类型
Console.WriteLine("Person Info:{0},{1}", person.Name, person.Age);
}
}
在用户自定义转换时,可能存在多种转换组合。
代码示例:
class Employee : Person { }
class Person
{
public string Name;
public int Age;
//将Person对象转换为int
public static implicit operator int(Person person)
{
return person.Age;
}
}
internal class Program
{
static void Main(string[] args)
{
Employee bill = new Employee();
bill.Name = "Wakaka";
bill.Age = 17;
//1.普通转换: Employee --> Person
//2.用户自定义转换: Person --> int
//3.普通转换: int --> float
float fVar = bill;
Console.WriteLine("Person Info: {0},{1}",bill.Name,fVar);
}
}
代码图解:
我们可以使用is运算符来检查转换是否会成功,避免盲目转换。
class Employee : Person { }
class Person
{
public string Name = "光头强";
public int Age = 25;
}
internal class Program
{
static void Main(string[] args)
{
Employee employee = new Employee();
Person person;
if (employee is Person) //检测employee是否能转换为Person类型
{
person = employee;
Console.WriteLine("Person Info: {0},{1}", person.Name,person.Age);
}
}
}
as运算符和强制运算符类似,但如果转换失败,返回null,而不是抛异常。
class Employee : Person { }
class Person
{
public string Name = "光头强";
public int Age = 25;
}
internal class Program
{
static void Main(string[] args)
{
Employee employee = new Employee();
Person person;
person = employee as Person;
if (person != null)
{
person = employee;
Console.WriteLine("Person Info: {0},{1}", person.Name,person.Age);
}
}
}
(注:本章学习总结自《C#图解教程》)