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