如此示例所示,将对象转换为接口转换对象与类之间有什么区别。
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之间有什么区别?
答案 0 :(得分:3)
在
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
的实例。
答案 1 :(得分:3)
唯一的区别在于编译器如何检查是否允许强制转换。
在第一个版本中,编译器会检查Lion
如何转换为Animal
,然后检查Animal
如何转换为IAnimal
。由于Lion
是Animal
而Animal
是IAnimal
,因此编译器可以安全地完成,编译器根本不会生成任何代码,它只是一个赋值。 / p>
在第二个版本中,编译器会检查Lion
如何转换为IAnimal
,然后检查IAnimal
是否与IAnimal
相同。由于演员阵容可以安全地完成,因此也不会在那里生成任何代码,它也只是一项任务。
由于Lion
是IAnimal
,您根本不需要进行任何投射,只需将其分配给变量:
IAnimal animal3 = lion;
在这种情况下,编译器将检查如何将Lion
强制转换为IAnimal
,并且因为这可以安全地完成,所以它不会生成任何用于转换的代码,只是生成赋值。
答案 2 :(得分:3)
在编译的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
答案 3 :(得分:1)
在您的第一个示例中,您正在执行向Animal
的显式转换,然后进行隐式转换以将其转换为IAnimal
,类似于IAnimal animal = (IAnimal)(Animal)lion;
。第二个例子只是执行隐式转换,并且,对于所有意图和目的,您可以在第二个示例中删除强制转换。