如果我创建了以下员工对象(简化)...
public class Employee
{
public Employee()
{
}
public String StaffID { get; set; }
public String Forename { get; set; }
public String Surname { get; set; }
}
...在员工对象中使用另一个属性员工来保存其管理员详细信息(如下所示)是否可以接受?< / p>
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; }
}
此外,为经理属性实例化员工对象的最佳方法是什么?显然,在构造函数中包含this.Manager = new Employee();
将导致无限循环。从员工继承的经理类是最好的方法(即使所有属性都相同)吗?
答案 0 :(得分:19)
对象可以确实引用了自己类型的对象。
这是大多数Node
类型对象的实现方式。
对于实例化 - 您可以传入Employee
对象以用作管理器(传递 null 而不管理器)。构造函数可以有多个重载:
public Employee(Employee manager)
{
this.Manager = manager;
}
答案 1 :(得分:6)
是的,对象可以包含对同一类的其他对象的引用。
其次,我不会在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; }
}
答案 2 :(得分:3)
此不可能的唯一情况是使用struct
; struct
直接包含 (而不是对数据的固定大小的引用),因此Employee
结构的大小必须是“struct Foo {
Foo foo;
}
结构的大小”其他字段加上员工的大小“,这是循环的。
特别是你不能拥有:
{{1}}
(或导致圆形大小的任何其他内容) - 编译器响应:
'Foo'类型的struct成员'Foo.foo'会在struct layout
中产生一个循环
然而,在所有其他情况下,它是好的;对于初始化问题,我会说:最初保持未分配状态,让调用者通过属性分配值。
答案 3 :(得分:1)
是的,您可以在Employee
内Employee
并且不会导致无限循环,Manager
对象的默认Employee
属性将为null
。
答案 4 :(得分:0)
它有效,你可以尝试s.th.像:
public class A
{
public A test { get; set; }
}
答案 5 :(得分:0)
特别是关于构造问题(我已经+ 1&#39; d Odeds回答) - 正如你所说在构造函数中构造一个实例是一个糟糕的举动。
然后问自己 - 为什么你还需要。在Manager
/ Employee
案例中,您无法始终确保员工始终拥有经理,如果他们不在,那么您就不应该使用new
ed空实例表示,但是为空。
当您的类型在属性上具有公共get / set访问器时,通常您可能会从某些外部源加载这些对象树,在这种情况下您无需担心。同样,您可以拥有一个构造函数,该构造函数接受管理器/员工关系等的其他Employee
个实例。
您还应该检查该构造函数中的循环关系 - 即员工不能成为某人的经理和他们的员工 - 尝试走孩子 - >父母关系,看看是否它永远结束了!
答案 6 :(得分:0)
首先,答案是是一个对象可以有一个包含自身实例的字段。它甚至可以有接受或返回同一个类的实例的方法,它甚至可以依赖于类的定义,例如:
public class Person : IComparable<Person> //legal, recursive definition
{
//fields (or properties) that are of type Person
public Person Father;
public Person Mother;
public List<Person> 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
'd,因此除非您自己创建,否则不会出现构造函数问题。所以,是,循环引用和无限循环可能存在一些问题(每个父级都有子级,其子级具有父级等...)但通常可以轻易地检测并避免它们。
我遇到这些问题的唯一一次是我在循环引用的对象上使用XML(或其他基于文本的)序列化。
答案 7 :(得分:0)
我试过这种方式,它对我有用:
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";
a.a.Name = "John";
Console.WriteLine("{0}, {1}", a.Name, a.a.Name);
}
}