考虑以下方法:
public PrintObjectHierarchy(object o)
{
Console.WriteLine(o.GetType.FullName);
object baseObject = PruneObjectToItsBaseObject(o);
if(!baseObject.GetType().Equals(typeof(object)))
PrintObjectHierarchy(baseObject);
else Console.WriteLine("System.Object");
}
例如,如果我写道:
class Form1 : Form
{
static void Main()
{
Form1 f1 = new Form1();
PrintObjectHierarchy(f1);
}
}
然后它应该打印给我:
MyNamespace.Form1
System.Windows.Form
System.Windows.Forms.ContainerControl
/*and so so till...*/
System.Object
但不幸的是,即使我将CAST对象转换为其BaseType,“C#Polymorphism”也会将其 VIEW 限制为基本类型,并且不会返回 REAL 引用一个 REAL 基础对象给我!让我们通过一个例子来描述它;如果我有
class Person {
public string Name;
public string LastName;
}
class President : Person {
public string password;
}
main(){
President pr = new President() {Name="John"; LastName="Smith"; password="js123" };
Person p = (Person)pr;
SendToAirportSystemAcrossInternet(p);
}
虽然我们认为 p 是人,但事实并非如此!它是总统而 p 只是一个视图,因此总统的密码将通过互联网传播!
关于如何修剪或切片对象的任何想法是创建真实基础对象的基础吗?
提前致谢!
答案 0 :(得分:2)
丹尼尔的解决方案有效;另一种类似的方法是编写一个“复制构造函数”并以这种方式创建一个新人。
所以,你的班级成为:
public class Person
{
public Person()
{
}
public Person(Person p)
{
this.name = p.name;
this.lastName = p.lastName
}
public string name;
public string lastName;
}
你可以从像这样的总统创建一个人:
President pres = new President() { name = "abc", lastName = "def", password = "kittens" };
Person p = new Person(pres);
这会从总统那里创造一个人,但是没有办法回到总统那里,也无法获得密码。如果你创建了一个这样的人并投给了一位总统,你将获得一个InvalidCastException
,我认为这就是你想要的。
答案 1 :(得分:2)
你想要实现的目标并不是很明显,但是当你对对象的继承层次结构感兴趣时,你很可能想要处理System.Type
的实例。这是您发布的第一个方法的工作版本,可能会提示您如何从那里继续:
static void PrintObjectHierarchy(object o)
{
Type t = o.GetType();
while (t != null)
{
Console.WriteLine(t.FullName);
t = t.BaseType;
}
}
答案 2 :(得分:1)
基本上,你不能做你想做的事。你应该重新设计,以便你没有这个要求。
正如我在评论中所指出的,当执行时类型是派生类时,基类中的一组字段可能是有效的,但对于该类的实例是无效的。此外,当以这种方式查看对象时,可能存在各种其他保护措施,这些保护措施简单地变为无效。例如,基类可以保存对值集合的引用,派生类期望验证添加到该集合的值。当对象被“修剪”时,将删除该验证,但是引用与之前相同的集合:
// EvenNumbersOnlyCollection rejects odd numbers
EvenNumberCollection derived = new EvenNumbersOnlyCollection();
NumberCollection pruned = Prune<NumberCollection>(derived);
pruned.Add(5);
// This would return 5 - the invariant is broken!
int shouldBeEven = derived.First();
目前尚不清楚为什么你认为这种修剪是个好主意,但你应该尝试以其他方式实现更广泛的目标。
答案 3 :(得分:0)
在C#中创建对象时,始终将其转换为其原始类型。即使您将其用作基础对象或接口,调用p.GetType()也将始终返回原始类型。
如果需要创建新对象,然后需要修剪其基础对象,则需要创建一个新的对象类型。例如:
public class ParentClass
{
public Parent(int feature1)
{
mFeature1 = feature1;
}
}
public class ChildClass : ParentClass
{
public ChildClass(int feature1, int feature2) : base(feature1)
{
mFeature2 = feature2;
}
}
...
...
ChildClass cc = new ChildClass(10, 20);
ParentClass pc = (ParentClass)cc; // pc still is of type ChildClass
ParentClass ccAsParent = new ParentClass(cc.Feature1); //ccAsParent is of type ParentClass
...
...
请记住,如果父类不是抽象,则只能执行此操作。