如何在 C#.NET 中将对象修剪为其基对象

本文关键字:对象 修剪 NET | 更新日期: 2023-09-27 18:33:32

请考虑以下方法:

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只是它的一个视图,所以总统的密码会通过互联网传播!

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

提前感谢!

如何在 C#.NET 中将对象修剪为其基对象

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

因此,您的人员类变为:

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,我认为这就是你想要的。

你想要实现的目标不是很明显,但是由于你对对象的继承层次结构感兴趣,你很可能想要处理System.Type的实例。这是您发布的第一种方法的工作版本,可能会为您提供有关如何从那里继续的提示:

static void PrintObjectHierarchy(object o)
{
    Type t = o.GetType();
    while (t != null)
    {
        Console.WriteLine(t.FullName);
        t = t.BaseType;
    }
}

基本上,你不能做你想做的事。您应该重新设计,以便您没有此要求。

正如我在注释中指出的,当执行时类型是派生类时,基类中的一组字段可能是有效的,但对于该类的实例无效。 此外,可能还有各种其他保护措施,当以这种方式查看对象时,这些保护措施将变得无效。例如,基类可以保存对值集合的引用,派生类应验证添加到该集合的值。当对象被"修剪"时,该验证将被删除,但引用与以前相同的集合:

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

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

在 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
...
...

请记住,只有当父类不是抽象的时,才能执行此操作。