为了账号安全,请及时绑定邮箱和手机立即绑定

c#使用派生类时的对象类型

c#使用派生类时的对象类型

C#
萧十郎 2021-10-31 11:04:01
具有以下代码:class TrxBase{    public string Prop1 { get; set; }    public string Prop2 { get; set; }}class Trx : TrxBase{    public string Prop3 { get; set; }}    static void Print(TrxBase trx)    {        if (trx is Trx trx1)        {            Console.WriteLine(trx1.Prop3);        }        else        {            Console.WriteLine("no match");        }    }    static void Main(string[] args)    {        Trx t = new Trx();        t.Prop1 = "prop 1";        t.Prop3 = "prop 3";        Print(t);    }上面的代码打印“prop 3”。据我所知。在 Print 方法中,该对象将作为 TrxBase 读取。如果是这种情况,Prop3 属性保存在哪里?程序如何知道我的参数实际上是一个 Trx 对象?
查看完整描述

2 回答

?
繁花不似锦

TA贡献1851条经验 获得超4个赞

您需要区分编译时类型(例如确定调用方法的哪个重载的那些)和运行时类型(例如反射使用的那些)。无论您对特定对象1 进行何种扭曲(将其转换为基类型等)都不会更改对象的运行时类型。

所以,仅仅因为你传递tPrint它要求一个TrxBase,它不会改变 tTrxBase

如果在 inside 中Print测试并确定它是 a Trx,则将其强制转换回该类型(隐藏在模式匹配语法中)并开始将其视为真正的类型(当然,尽管,它可能是一种更源自Trx.


额外阅读:埃里克·利珀特的代表和身份


1如果您了解引用更改转换为您提供了一个对象。这在上面的奖励阅读中也有进一步的解释。


查看完整回答
反对 回复 2021-10-31
?
心有法竹

TA贡献1866条经验 获得超5个赞

这就是 C# 的工作方式,当您将派生类型对象传递给具有基类型对象参数的方法时,编译器只需获取此派生对象并将其解释为基类。

在您的情况下,您将派生 ( Trx) 对象传递给带有TrxBase参数的方法。因此,现在在 的范围内Print(TrxBase trx)trx将被视为TrxBase, 但随后您将使用模式匹配来确定这是否trx可以表示为更派生的Trx对象类型,在您的情况下是正确的,因此可以打印prop 3

可以将派生类型转换为更多基类型,但另一种方式将导致InvalidCastException来自 CLR。因为如果您考虑一下 - 假设您分配类型为的新对象TrxBase,CLR 分配器将在堆(或堆栈,如果值类型)上分配此类对象,并具有该对象具有的所有所需属性。现在,如果您从 CLR 请求将此特定对象转换为更具体的对象,您最终会请求将此特定内存布局更改为 CLR 不支持的另一个(从您的特定对象添加字段、属性等)。


查看完整回答
反对 回复 2021-10-31
  • 2 回答
  • 0 关注
  • 269 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信