我们已经知道了在值类型之间可以进行显式转换和隐式转换,在值类型与引用类型之间可以进行装箱与拆箱。可是在引用类型之间也可以进行显式转换和隐式转换,但是这种转换所改变的只是对象的引用的类型,并改变不了对象本身的类型。与值类型的显式转换一样,引用类型的显式转换也存在数据丢失的风险。
隐式引用转换
以下转换不会抛出异常,转换总是能成功:
(1) 从派生类到基类
(2) 从派生接口到基接口
(3) 从类到接口(该类实现了该接口)
(4) 从null到任何类
显式引用转换
以下转换有可能抛出异常,转换不一定能成功:
(1) 从基类到派生类
(2) 从接口到接口(基接口到派生接口或俩接口没有关系)
(3) 从接口到类(该类实现了该接口或该类未密封)
(4) 从类到接口(该类未实现该接口且该类未密封)
以上说的从*到#中,*指类或接口的引用,#指类名或接口名。
若要访问派生类型的方法,需要将值强制转换回该派生类型。不过,在这些情况下,如果只尝试进行简单的强制转换,会导致引发 InvalidCastException 的风险。这就是 C# 提供 is 和 as 运算符的原因。您可以使用这两个运算符来测试强制转换是否会成功,而没有引发异常的风险。通常,as 运算符更高效一些,因为如果可以成功进行强制转换,它会实际返回强制转换值。而 is 运算符只返回一个布尔值。因此,如果只想确定对象的类型,而无需对它进行实际强制转换,则可以使用 is 运算符。
class Program
{
interface f
{
void save();
}
class B
{
}
class A:B,f
{
public void save() { }
}
static void Main(string[] args)
{
A a =new A(); @@@
A b = new A();
Console.WriteLine(Equals(a, b));
B c =new A(); @@@
f v = new A(); @@@
}
}
@@@处 根据 类1 a=new 类1(); 能写出 X a=new 类1(); 只要类1能隐式引用转换成X就能这么写
is与as的用法
is 如:以上代码中判断A类的引用的类型是否能强制转换成B类型
if (a is B) //is前面是引用,后面是类名或接口名
{
B b1 = (B)a; //如果返回值为true,即能进行强制转换,就进行转换
}
else
{
Console.WriteLine("A类型的引用a不能强制转换成B类型")
}
以上判断方法可以简写成
B b1 = a as B;
这就是as的用法,不过as不会抛出异常,即如果进行的强制转换不能成功,则运算结果为null,如果在后面的代码中使用这些引用,就会抛出使用空引用的异常。