为什么对象在向上转换时会保存属性

时间:2018-06-27 08:26:33

标签: c# upcasting

关于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));
        }
    }

...我还可以看到密码属性。问题是-为什么在上传后将其保存?

2 个答案:

答案 0 :(得分:13)

  

问题是-为什么在上传后将其保存?

因为强制转换根本不会更改 object 。它只是改变了您查看对象的方式。

认为它就像一个人。人们可能会用不同的方式查看您的信息:

  • 同事
  • 经理
  • 家庭成员
  • 朋友

他们只“看到”您的某些方面,但这并不会改变您的身份。

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

(请注意,调用用户定义的转换(例如,从XElementstring的转换)是完全不同的。返回的是对新对象的引用,而不仅仅是现有对象的引用对象以另一种方式。)

如果只想查看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)}");
    }
}

尽管我不确定在大多数情况下进行反射操作是否特别有用。

答案 1 :(得分:1)

当您将任何类型的对象转换为它们的基本类型时,您只是持有该对象的基本类型。

对象不会因此失去其属性。

如果看到最简单的示例:使用非通用集合

Admin中添加某个对象(例如ArrayList类)时,实际上是将该对象转换为object类型(装箱),然后将其存储为arraylist。因此,这是向上转换的终极示例!怎么样?

  

对象类型是.NET Framework中Object的别名。在C#的统一类型系统中,所有类型(预定义和用户定义的类型,引用类型和值类型)都直接或间接继承自Object。

Full Post

现在object类型不包含userName password之类的属性。 因此,当您尝试直接从arraylist获取的对象访问那些属性时,将无法执行此操作。因为当前您正在处理类型object,并且您将只能访问object类型支持的那些属性或成员(但是在这里您没有访问权限,但是那些属性仍然存在)。另外,如其他答案GetType()方法中所述,也肯定会返回其原始类型。

但是,当您通过将其原始对象转换回Admin类型(取消装箱)而从数组列表中获取该原始对象时,您将看到对象中的属性与以前一样。唯一更改的是,现在您可以访问它们,因为Admin类型支持它们。

Read this for more detail