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

时间:2012-01-17 10:03:12

标签: c# object properties

如果我创建了以下员工对象(简化)...

 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();将导致无限循环。从员工继承的经理类是最好的方法(即使所有属性都相同)吗?

8 个答案:

答案 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)

是的,您可以在EmployeeEmployee并且不会导致无限循环,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);
    }
}