为什么可以';当两者共享接口时,我从一种类型转换为另一种类型

本文关键字:一种 类型 另一种 类型转换 接口 共享 为什么 | 更新日期: 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接口,这很好,你可以与这两种类型的对象交谈,只知道它们实现了一些共同的东西,但这不是同一类型的对象,你不能从一个转换到另一个。

仅仅因为comICompany并不意味着它指向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,你会尝试使用一个Temporaryt对象不拥有的属性。编译器不允许您这样做。