为什么可以';当两者共享接口时,我从一种类型转换为另一种类型
本文关键字:一种 类型 另一种 类型转换 接口 共享 为什么 | 更新日期: 2023-09-27 18:20:45
这是一个演示控制台应用程序(如果需要,您应该可以将其复制并粘贴到VS中)
public class Program
{
static void Main(string[] args)
{
Temporary t = new Temporary(); //I know it should be ICompany t
t.Name = "My Name";
var com = (ICompany)t;
var result = (Company)com; //Kaboom
}
}
public class Temporary : ICompany
{
public string Name { get; set; }
}
public class Company : ICompany
{
public string Name { get; set; }
}
public interface ICompany
{
string Name { get; }
}
希望上面的代码是直接的。
我的问题是演员阵容以及为什么会失败。我知道我可以将原始变量t
更改为ICompany类型(根据注释),但我的问题是为什么转换失败。
我的理解(希望能解释我错在哪里)是
var com = (ICompany)t
将Temporary
类型的t
铸造为ICompany
。这与Temporary implements
ICompany `一样适用
这意味着t
现在属于ICompany
类型。所以,希望
var result = (Company)com; //Kaboom
这将com
(类型为ICompany)转换为Company
为什么失败,为什么它知道t
仍然是Temporary
类型
这个问题有些混乱,这可能是它的原因。
此声明:
这意味着,t现在属于ICompany类型。所以,希望
不正确。不,t
仍然是Temporary
类型,根据其声明:
Temporary t = new Temporary();
实际上,这一行中有两个地方的类型很重要。它是您构建的对象的实际类型,也是您放置引用的变量的类型。
当然,你可以这样写:
ICompany t = new Temporary();
但这只会改变变量的类型,底层对象的类型仍然是Temporary
。
然后,您试图将实际对象(仍然是Temporary
)强制转换为Company
,但这将失败,因为Temporary
不是Company
。
然而,它们都实现了相同的ICompany
接口,这很好,你可以与这两种类型的对象交谈,只知道它们实现了一些共同的东西,但这不是同一类型的对象,你不能从一个转换到另一个。
仅仅因为com
是ICompany
并不意味着它指向Company
实例。它可能指向从ICompany
派生的(潜在的)无限数量的类型。是的,你可以查看代码并知道这一点,但编译器并不是这么看的
在您的情况下尤其如此,因为实际类型是Temporary
,而不是Company
。
不能只将Company类强制转换为Temporary类,因为尽管它们都派生自ICompany并且具有相同的字段,编译器仍然认为它们是不同的类。唯一允许的类强制转换是从子类到其父类。在这种情况下,您实际上会在子类上放置一个"掩码",以隐藏其独占字段,并使其表现为其父类,但您仍然可以将其转换回原始子类。
不能将接口强制转换为这样的实现。铸造不是转换。铸造只意味着:"把这个项目当作其他类型来处理",但下面的数据保持不变。通过这种方式,您可以将任何specific类型强制转换为更通用的类型——只有当下面的对象属于您要强制转换的类型(或其他类型)时,才允许使用另一种方式。想象一下,您的类定义如下所示:
public class Temporary : ICompany
{
public string Name { get; set; }
}
public class Company : ICompany
{
public string Name { get; set; }
public string OtherProperty {get; set;}
}
如果你调用((Company)t).OtherProperty
,你会尝试使用一个Temporary
t对象不拥有的属性。编译器不允许您这样做。