强制转换接口和类对象

本文关键字:对象 接口 转换 | 更新日期: 2023-09-27 18:02:48

将对象强制转换为接口将对象强制转换为类的区别是什么?

namespace ConsoleApplication1
{
    interface IAnimal
    {
        string Sound();
    }
    class Animal : IAnimal
    {
        public string Sound()
        {
            return "Animal sound";
        }
    }
    class Lion : Animal, IAnimal
    {
        public string Sound()
        {
            return "Roarrrrr";
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Lion lion = new Lion();
            IAnimal animal = (Animal)lion; // variant 1
            IAnimal animal2 = (IAnimal)lion; // variant 2
            Console.WriteLine(animal.Sound());
        }
    }
}

变量1和变量2的区别是什么?

强制转换接口和类对象

唯一的区别在于编译器如何检查强制类型转换是否被允许。

在第一个变体中,编译器检查Lion如何可以强制转换为Animal,然后检查Animal如何可以强制转换为IAnimal。由于LionAnimal, AnimalIAnimal,所以这两种类型的强制转换都是安全的,编译器根本不生成用于强制转换的代码,它只是一个赋值。

在第二个变体中,编译器检查Lion如何可以强制转换为IAnimal,然后检查IAnimal是否与IAnimal相同。因为强制转换可以安全地完成,所以它也不生成用于强制转换的代码,它也只是一个赋值。

因为Lion是一个IAnimal,你根本不需要做任何类型转换,你可以把它赋值给变量:

IAnimal animal3 = lion;

在这种情况下,编译器将检查Lion如何可以强制转换为IAnimal,因为这可以安全地完成,它不生成任何强制转换代码,只是赋值。

In

IAnimal animal = (Animal)lion;

存在隐式转换,因为animal被声明为IAnimal,而Animal可转换为IAnimal(因为类实现了该接口)。

对应于

Lion lion = new Lion();
Animal a = lion;
IAnimal ia = a;

所有这些转换都是可能的。

但是,你也可以这样写:

IAnimal lion = new Lion();

另一方面,如果你写了

var animal = (Animal)lion;

animal应该是Animal的一个实例。

从字面上看,在编译后的il中没有差异,但是当您将Animal赋值给IAnimal时,编译器会执行隐式转换。编译器很乐意这样做,因为它知道Animal实现了IAnimal

这是IL,它显示了我的意思。

IL_0001:  newobj      UserQuery+Lion..ctor //Create new lion
IL_0006:  stloc.0     // store it in variable lion
IL_0007:  ldloc.0     // load variable lion
IL_0008:  stloc.1     // store it in variable animal
IL_0009:  ldloc.0     // load variable lion
IL_000A:  stloc.2     // store it in variable animal2
IL_000B:  ldloc.1     // load variable animal
IL_000C:  callvirt    UserQuery+IAnimal.Sound //Call animal.Sound 
IL_0011:  call        System.Console.WriteLine //With the result call Console.WriteLine

在您的第一个示例中,您正在执行显式转换到Animal,然后进行隐式转换,将其转换为类似于IAnimal animal = (IAnimal)(Animal)lion;IAnimal。第二个示例只是执行隐式转换,出于各种目的,您可以删除第二个示例中的强制转换。