Доступ к свойствам из инициализатора объекта

У меня есть следующий класс Person

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string FullName
    {
        get { return FirstName + " " + LastName; }
    }
    public IEnumerable<Person> Children { get; set; }
}

Я мог бы инициализировать его так:

Person p = new Person() { FirstName = "John", LastName = "Doe" };

Но можно ли ссылаться на другое свойство Person в инициализаторе объекта, чтобы я мог сделать, например, что-то вроде этого?

Person p = new Person()
{
    FirstName = "John",
    LastName  = "Doe",
    Children  = GetChildrenByFullName(FullName);
};

ИЗМЕНИТЬ

Ради вопроса, ссылочное свойство не должно вычисляться в соответствии с другими свойствами, но его значение может быть установлено в конструкторе.

Спасибо


person Adi Lester    schedule 08.08.2012    source источник


Ответы (3)


Вы не можете сделать это:

void Foo()
{ 
  String FullName = "";

  Person p = new Person()
  {
    FirstName = "John",
    LastName  = "Doe",
    Children  = GetChildrenByFullName(FullName); // is this p.FullName 
                                                 // or local variable FullName?
  };
}
person Dennis    schedule 08.08.2012
comment
Даже если вы укажете p.FullName, это не сработает, а это позор. - person Rawling; 08.08.2012
comment
@Роулинг: почему стыдно? Инициализатор объекта является частью объявления переменной, поэтому компилятор здесь справедлив - p используется до его инициализации. - person Dennis; 08.08.2012
comment
Этот код создает new Person(), а затем вызывает для него установщики свойств. Когда вы вызываете FullName, Person уже создано, так что это свойство можно вызвать. К сожалению, Person построен во временной переменной, а не в p напрямую, поэтому вы не можете получить доступ к его свойствам таким образом. (Вероятно, для этого есть веская причина, но в данном конкретном случае это позор.) - person Rawling; 08.08.2012
comment
(Я понимаю вашу точку зрения о том, что это часть декларации.) - person Rawling; 08.08.2012

Нет. Находясь внутри инициализатора объекта, вы не находитесь внутри экземпляра класса. Другими словами, у вас есть доступ только к общедоступным свойствам, которые можно установить.

Явно:

class Person
{
    public readonly string CannotBeAccessed;
    public  string CannotBeAccessed2 {get;}
    public void CannotBeAccessed3() { }

    public string CanBeAccessed;
    public string CanBeAccessed2 { set; }
} 
person Justin Harvey    schedule 08.08.2012
comment
Собственность, о которой он говорит, является общественной собственностью. - person Rawling; 08.08.2012
comment
У меня может быть другое свойство public string PersonId { get; set; }, но я тоже не смогу получить к нему доступ. - person Adi Lester; 08.08.2012
comment
@Adi Точно: причина, по которой вы не можете этого сделать, не в том, потому что вы не можете получить доступ к личным свойствам. - person Rawling; 08.08.2012
comment
@Rawling, я больше говорил об ограничении доступа к свойствам/методам, которые можно использовать для установки свойства. Другими словами, вы можете получить доступ к свойствам для «настройки», но не для «получения». - person Justin Harvey; 08.08.2012

Я думаю, что вы сможете решить свою проблему, поддерживая свои свойства с помощью частных локальных переменных. например

class Person {
    private string m_FirstName = string.Empty;
    private string m_LastName = string.Empty;

    public string FirstName {
        get { return m_FirstName; }
        set { m_FirstName = value; }
    }

    public string LastName {
        get { return m_LastName; }
        set { m_LastName = value;}
    }

    public string FullName {
         get { return m_FirstName + " " + m_LastName; }
    }

    public IEnumerable<Person> Children { get; set; }
}

Предполагая, что инициализатор объекта устанавливает свойства в том порядке, в котором вы указываете их в коде инициализации (и так и должно быть), локальные переменные должны быть доступны (внутренне через свойство FullName, доступное только для чтения).

person Kevin    schedule 08.08.2012