如何在 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只是它的一个视图,所以总统的密码会通过互联网传播!
关于如何修剪或切片对象以创建真正的基本对象的任何想法?
提前感谢!
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
...
...
请记住,只有当父类不是抽象的时,才能执行此操作。