Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
自定义C#对象能否包含与自身类型相同的属性?_C#_Object_Properties - Fatal编程技术网

自定义C#对象能否包含与自身类型相同的属性?

自定义C#对象能否包含与自身类型相同的属性?,c#,object,properties,C#,Object,Properties,如果我创建了以下员工对象(简化) 。。。在Employee对象中有另一个类型也为Employee的属性来保存经理的详细信息(如下所示)是否可以接受 另外,为经理属性实例化员工对象的最佳方法是什么?显然包括this.Manager=new Employee()将导致无限循环。管理者从员工继承的类是否是最好的方法(即使所有属性都相同)?一个对象确实可以引用它自己类型的对象 这就是大多数节点类型对象的实现方式 至于实例化-您可以传入Employee对象以用作经理(传入null表示无经理)。构造函数可以

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

。。。在Employee对象中有另一个类型也为Employee的属性来保存经理的详细信息(如下所示)是否可以接受


另外,为经理属性实例化员工对象的最佳方法是什么?显然包括
this.Manager=new Employee()将导致无限循环。管理者员工继承的类是否是最好的方法(即使所有属性都相同)?

一个对象确实可以引用它自己类型的对象

这就是大多数
节点
类型对象的实现方式

至于实例化-您可以传入
Employee
对象以用作经理(传入null表示无经理)。构造函数可以有多个重载:

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

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

其次,我不会在cunstructor中创建新员工,而是像这样注入它:

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

它有效,你可以试试s.th。比如:

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

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

特别是在构造问题上(我有+1个Odeds答案)-正如您所说,在构造函数中构造实例是一个糟糕的举动

但是问问你自己——你为什么要这么做呢。在您的
Manager
/
Employee
案例中,您不能总是确保员工总是有一个经理,如果他们没有,那么您不应该使用
新的
ed空实例来表示,而应该使用空实例

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


您还应该检查该构造函数中的循环关系-即员工不能是某人的经理和员工-尝试遍历子->父关系,看看是否结束

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

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;
   }
}
public-class-Person:IComparable//legal,递归定义
{
//类型为Person的字段(或属性)
公众人物父亲;
公众人物母亲;
公开儿童名单;
//方法,该方法将人员作为参数
公共学校家长(潜在家长)
{
....
}
//使人恢复知觉的方法
公众人物克隆()
{
//TODO:真正的实施即将到来
}
公众人物(){}
//将人员作为参数的构造函数
公众人物(人父、人母)
{
父亲=父亲;
母亲=母亲;
}
}
默认情况下,所有引用值都是
null
'd,因此除非您自己创建一个构造函数,否则不会出现构造函数问题。因此,,循环引用和无休止的循环可能会出现一些问题(每个父对象都有子对象,子对象都有父对象等等),但通常可以检测到并避免这些问题


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

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

特别是你不能有:

struct Foo {
    Foo foo;
}
(或任何可能导致循环大小的内容)-编译器响应:

类型为“Foo”的结构成员“Foo.Foo”在结构布局中导致循环


然而,在所有其他情况下,这是罚款;关于初始化的问题,我想说:先让它不赋值,然后让调用者通过属性赋值。

我尝试了这种方法,它对我有效:

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

... 但显然,您不应该无条件地初始化构造函数中的属性/字段(因为这会导致
StackOverflowException
OutOfMemoryException
,具体取决于对象的大小、分配的堆栈大小和您的总可用内存)@Tobias上述代码不会导致任何异常。如果您使用
this.Manager=new Employee()
对其进行初始化,则会产生一个注释。注释是直接附加到答案的(因此是…,我在添加.ctor代码块之前发布了注释。-1用于厚颜无耻的编辑,在@DennisTraub首先发布注释之后添加重载的员工构造函数;)@AndrewBurnett-Thompson博士——你似乎忽略了SO类似维基的属性。就目前的情况而言,我只是补充了这一点,没有考虑其他答案——不过还是要感谢你的假设。编辑应该会让答案更好——假设我把它从另一个答案上提出来,那怎么会让它变差呢?你否决了一个答案,因为它变得更好了?@FelixK。这有点苛刻,这是一个很好的问题,我对此很感兴趣。在构造函数中,将导致无限循环。记住,并非所有人都是experts@V4Vendetta没错,
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;
    }
}
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);
    }
}