Может ли объект Custom C # содержать свойство того же типа, что и он сам? - PullRequest
10 голосов
/ 17 января 2012

Если я создал следующий Сотрудник объект (упрощенно) ...

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

Кроме того, как лучше всего создать экземпляр объекта Employee для свойства Manager ? Очевидно, что включение this.Manager = new Employee(); в конструктор вызовет бесконечный цикл. Будет ли Manager класс, унаследованный от Employee , лучшим способом (даже если все свойства будут идентичны)?

Ответы [ 8 ]

19 голосов
/ 17 января 2012

Объект может действительно иметь ссылку на объект своего собственного типа.

Так реализовано большинство объектов типа Node.

Что касаетсясоздание экземпляра - вы можете передать объект Employee для использования в качестве менеджера (передача null без менеджера).Конструкторы могут иметь несколько перегрузок:

public Employee(Employee manager)
{
   this.Manager = manager;
}
6 голосов
/ 17 января 2012

Да, объект может содержать ссылки на другие объекты того же класса.

А во-вторых, я бы не стал создавать нового сотрудника в конструкторе, а вставил бы его так:

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; }
}
3 голосов
/ 17 января 2012

Единственный сценарий, в котором невозможен , возможен с struct;struct содержится непосредственно (а не является ссылкой на данные фиксированного размера), поэтому размер структуры Employee должен быть равен "размеру других полей плюс размерof Employee ", который является круглым.

В частности, вы не можете иметь:

struct Foo {
    Foo foo;
}

(или что-либо еще, что привело бы к размеру круга) - компилятор отвечает:

Член структуры 'Foo.foo' типа 'Foo' вызывает цикл в структуре структуры

Однако во всех остальных случаях это нормально;с вопросом инициализации, я бы сказал: просто оставьте его неназначенным изначально, и позвольте вызывающей стороне присвоить значение через свойство.

1 голос
/ 17 января 2012

Да, вы можете иметь Employee внутри Employee, и это не вызовет бесконечный цикл, по умолчанию свойство Manager объекта Employee будет иметь значение null.

0 голосов
/ 22 мая 2014

Я попробовал этот способ, и он работал для меня:

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);
    }
}
0 голосов
/ 17 января 2012

Во-первых, ответ Да объект может иметь поле, содержащее его экземпляр. У него даже могут быть методы, которые принимают или возвращают экземпляры одного и того же класса, и он может даже зависеть от себя в определении класса, например:

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, поэтому у вас не будет проблем с конструктором, если вы не создадите его самостоятельно. Итак, Да , могут быть некоторые проблемы с циклическими ссылками и бесконечными циклами (у каждого родителя есть дети, у которых есть дети, у которых есть родители и т. Д.), Но обычно их можно легко обнаружить и избежать.

Единственный раз, когда я сталкивался с подобными проблемами, это когда я использовал сериализацию XML (или другую текстовую) для объектов с круговой ссылкой.

0 голосов
/ 17 января 2012

В частности, по вопросу построения (у меня +1 ответ Одедса) - как вы говорите, создание экземпляра в конструкторе - плохой ход.

Но тогда спросите себя - зачем вам это вообще нужно? В вашем случае Manager / Employee вы не всегда можете быть уверены, что у сотрудника всегда есть менеджер, а если его нет, вам не следует использовать пустой экземпляр new ed для обозначения этого, но ноль.

Когда ваш тип будет иметь общедоступные методы доступа get / set к свойствам, обычно вы, вероятно, будете загружать эти деревья объектов из какого-то внешнего источника, и в этом случае вам не о чем беспокоиться. Точно так же у вас может быть конструктор, который принимает другие Employee экземпляры для отношений Менеджер / Сотрудник и т. Д.

Вы также должны проверять циклические отношения в этом конструкторе - т. Е. Сотрудник не может быть чьим-либо менеджером и его сотрудником - попробуйте пройти по этому вопросу отношения между детьми и родителями и посмотреть, закончится ли он когда-нибудь!

0 голосов
/ 17 января 2012

Это работает, вы можете просто попробовать s.th. как:

public class A
{
    public A test { get; set; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...