Custom C#对象是否可以包含与其自身类型相同的属性?

如果我创建了以下Employee对象(简化)…

public class Employee { public Employee() { } public String StaffID { get; set; } public String Forename { get; set; } public String Surname { get; set; } } 

…在Employee对象中有另一个属性,同时也是Employee来保存其经理的详细信息(如下所示),是否可以接受?

  public class Employee { public Employee() { } public String StaffID { get; set; } public String Forename { get; set; } public String Surname { get; set; } public Employee Manager { get; set; } } 

另外,为Manager属性实例化Employee对象的最佳方法是什么? 显然包括this.Manager = new Employee(); 在构造函数中将导致无限循环。 从Employeeinheritance的Manager类是最好的方法(即使所有属性都相同)?

对象确实可以引用其自身类型的对象。

这是大多数Node类型对象的实现方式。

至于实例化 – 您可以传入Employee对象以用作管理器(对于没有管理器传递null )。 构造函数可以有多个重载:

 public Employee(Employee manager) { this.Manager = manager; } 

是的,对象可以包含对同一类的其他对象的引用。

其次,我不会在cunstructor中创建一个新的Employee,而是像这样注入它:

 public class Employee { public Employee(Employee manager) { this.Manager = manager; } public String StaffID { get; set; } public String Forename { get; set; } public String Surname { get; set; } public Employee Manager { get; set; } } 

唯一不可能的情况是struct ; struct 直接包含(而不是对数据的固定大小引用),因此Employee结构的大小必须是“其他字段的大小加上Employee的大小”,这是循环的。

特别是你不能拥有:

 struct Foo { Foo foo; } 

(或任何其他会导致圆形大小的东西) – 编译器响应:

类型为’Foo’的结构成员’Foo.foo’会在结构布局中产生一个循环

但是,在所有其他情况下,它是好的; 对于初始化问题,我会说:最初保持未分配状态,让调用者通过属性分配值。

是的,您可以在Employee中拥有Employee并且它不会导致无限循环,默认情况下, Employee对象的Manager属性将为null

它有效,你可以尝试s.th. 喜欢:

 public class A { public A test { get; set; } } 

特别是关于构造的问题(我已经给了Odeds回答了1次) – 正如你所说在构造函数中构造一个实例是一个糟糕的举动。

但后来问问自己 – 为什么你还需要。 在您的Manager / Employee案例中 – 您无法始终确保员工始终拥有经理,如果他们不经理,那么您不应该使用new ed空实例来表示,而是null。

当您的类型在属性上具有公共get / set访问器时,通常您可能会从某些外部源加载这些对象树,在这种情况下您无需担心。 同样,您可以拥有一个构造函数,该构造函数接受Manager / Employee关系等的其他Employee实例。

您还应该检查该构造函数中的循环关系 – 即员工不能是某人的经理和他们的员工 – 尝试走孩子 – >父母关系,看看它是否会结束!

首先,答案是肯定的,对象可以有一个包含自身实例的字段。 它甚至可以有接受或返回同一个类的实例的方法,它甚至可以依赖于类的定义,例如:

 public class Person : IComparable //legal, recursive definition { //fields (or properties) that are of type Person public Person Father; public Person Mother; public List Children; // method that takes a Person as a parameter public bool IsParent(Person potentialParent) { .... } //method that returs a Person public Person Clone() { //TODO: real implementation coming soon } public Person(){} //constructor that takes persons as arguments public Person(Person father, Person Mother) { Father = father; Mother = mother; } } 

默认情况下,所有引用值都为null ,因此除非您自己创建构造函数,否则不会出现构造函数问题。 所以, 是的 ,循环引用和无限循环可能存在一些问题(每个父母都有孩子,孩子有父母等……)但通常可以轻易地检测和避免它们。

我遇到这些问题的唯一一次是我在循环引用的对象上使用XML(或其他基于文本的)序列化。

我试过这种方式,它对我有用:

 class Program { static void Main(string[] args) { A a = new A(new A()); } } public class A { public string Name { get; set; } public A a; public A() { } public A(A _a) { a = _a; } } 

现在您可以在Main()函数中使用它,如:

 class Program { static void Main(string[] args) { A a = new A(new A()); a.Name = "Roger"; aaName = "John"; Console.WriteLine("{0}, {1}", a.Name, aaName); } }