关于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));
}
}
...我还可以看到密码属性。问题是-为什么在上传后将其保存?
答案 0 :(得分:13)
问题是-为什么在上传后将其保存?
因为强制转换根本不会更改 object 。它只是改变了您查看对象的方式。
认为它就像一个人。人们可能会用不同的方式查看您的信息:
他们只“看到”您的某些方面,但这并不会改变您的身份。
同样,简单的引用转换不会更改对象。如果调用user.GetType()
,它将仍然报告对象的 actual 类型。只是当您通过特定的镜头(无论是接口还是基类)查看对象时,您只会看到镜头向您显示的成员。
(请注意,调用用户定义的转换(例如,从XElement
到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)}");
}
}
尽管我不确定在大多数情况下进行反射操作是否特别有用。
答案 1 :(得分:1)
当您将任何类型的对象转换为它们的基本类型时,您只是持有该对象的基本类型。
对象不会因此失去其属性。
如果看到最简单的示例:使用非通用集合
在Admin
中添加某个对象(例如ArrayList
类)时,实际上是将该对象转换为object
类型(装箱),然后将其存储为arraylist。因此,这是向上转换的终极示例!怎么样?
对象类型是.NET Framework中Object的别名。在C#的统一类型系统中,所有类型(预定义和用户定义的类型,引用类型和值类型)都直接或间接继承自Object。
现在object
类型不包含userName
password
之类的属性。
因此,当您尝试直接从arraylist获取的对象访问那些属性时,将无法执行此操作。因为当前您正在处理类型object
,并且您将只能访问object
类型支持的那些属性或成员(但是在这里您没有访问权限,但是那些属性仍然存在)。另外,如其他答案GetType()
方法中所述,也肯定会返回其原始类型。
但是,当您通过将其原始对象转换回Admin
类型(取消装箱)而从数组列表中获取该原始对象时,您将看到对象中的属性与以前一样。唯一更改的是,现在您可以访问它们,因为Admin
类型支持它们。