1

考虑以下方法:

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

但不幸的是,即使我将对象转换为它的 BaseType,“C# 多态性”也只会将其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只是它的一个视图,所以总统的密码会在互联网上传播!

关于如何将对象修​​剪或切片以创建真正的基础对象的任何想法?

提前致谢!

4

4 回答 4

2

您要实现的目标不是很明显,但是当您对对象的继承层次结构感兴趣时,您很可能希望处理System.Type. 这是您发布的第一种方法的工作版本,它可能会提示您如何从那里继续:

static void PrintObjectHierarchy(object o)
{
    Type t = o.GetType();
    while (t != null)
    {
        Console.WriteLine(t.FullName);
        t = t.BaseType;
    }
}
于 2012-05-09T10:59:13.490 回答
2

丹尼尔的解决方案有效;另一种类似的方法是编写一个“复制构造函数”并以这种方式创建一个新人。

因此,您的 person 类变为:

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);

这从总统那里创建了一个人,但没有办法回到总统那里,也没有办法得到密码。如果您创建一个 this was 并投给一位总统,您将得到一个InvalidCastException,我认为这就是您想要的。

于 2012-05-09T10:34:55.150 回答
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();

目前尚不清楚为什么您认为这种修剪是个好主意,但您应该尝试以其他方式实现更广泛的目标。

于 2012-05-09T15:59:54.113 回答
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
...
...

请记住,只有在父类不是abstract时才能这样做。

于 2012-05-09T10:27:12.020 回答