首页 > 解决方案 > 为什么对象在向上转换时会保存属性

问题描述

我有一个关于 c# 中向上转换的简单问题。例如我有两个接口:

interface IUSer
{
    string UserName { get; set; }
}

interface IAdmin: IUSer
{
    string Password { get; set; }
}

...和一个实现 IAdmin 接口的类:

class Admin : IAdmin
{
    public string Password { get; set; }
    public string UserName { get; set; }
}

当我创建 Admin 类型的对象并尝试将其向上转换为 IUser 时,从技术上讲,我只能访问 UserName user.UserName:

var admin = new Admin() { UserName = "Arthur", Password = "hello" };
var user = (IUSer)admin;
Console.WriteLine( user.UserName );

...但是如果我使用反射循环通过这个对象的属性,就像这样:

    private static void Outputter(IUSer user)
    {
        foreach (var prop in user.GetType().GetProperties())
        {
            Console.WriteLine(prop.Name +  " " + prop.GetValue(admin));
        }
    }

...我还可以看到密码属性。问题是 - 为什么它在向上转换时被保存?

标签: c#upcasting

解决方案


问题是 - 为什么它在向上转换时被保存?

因为投射根本不会改变对象。它只是改变了您查看对象的方式。

把它想象成一个人。人们可能会以不同的方式查看您:

  • 一个同事
  • 经理
  • 一位家庭成员
  • 一个朋友

他们只“看到”你的某些方面,但这并不会改变你是谁。

同样,简单的引用转换也不会改变对象。如果你调用user.GetType()它,它仍然会报告对象的实际类型。只是当您通过特定镜头(无论是接口还是基类)查看对象时,您只会看到镜头显示给您的成员。

(请注意,调用用户定义转换的强制转换,例如从XElementto强制转换string是完全不同的。它返回对新对象的引用,而不仅仅是以不同的方式关注现有对象。)

如果您只想查看IUser属性,请使用typeof(IUser).GetProperties()而不是先调用GetType()

private static void Outputter(IUser user)
{
    foreach (var prop in typeof(IUser).GetProperties())
    {
        Console.WriteLine($"{prop.Name}: {prop.GetValue(user)}");
    }
}

尽管我不确定在大多数情况下通过反射来做到这一点特别有用。


推荐阅读