4

I have the following Person class

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

I could initialize it like this:

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

But is it possible to reference another property of Person in the object initializer, so I could do for example something like this?

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

EDIT

For the sake of the question, the referenced property doesn't have to be calculated according to other properties, but its value could be set in the constructor.

Thanks

Adi Lester
  • 24,731
  • 12
  • 95
  • 110

3 Answers3

4

You can't do that:

void Foo()
{ 
  String FullName = "";

  Person p = new Person()
  {
    FirstName = "John",
    LastName  = "Doe",
    Children  = GetChildrenByFullName(FullName); // is this p.FullName 
                                                 // or local variable FullName?
  };
}
Dennis
  • 37,026
  • 10
  • 82
  • 150
  • Even if you specify `p.FullName` it won't work, which is a shame. – Rawling Aug 08 '12 at 07:55
  • @Rawling: why it is a shame? Object initializer is a part of variable declaration, so the compiler is fair here - `p` used before it has initialized. – Dennis Aug 08 '12 at 08:02
  • 1
    This code constructs a `new Person()`, then calls property setters on it. When you call `FullName` the `Person` has been constructed so the property is there to be called. Unfortunately the `Person` is constructed in a temporary variable rather than in `p` directly so you can't access its properties like this. (There's probably a good reason for this, but in this particular case it's a shame.) – Rawling Aug 08 '12 at 08:08
  • (I see your point about how it's part of the declaration.) – Rawling Aug 08 '12 at 08:09
-2

No. When inside the object initialiser, you are not inside an instance of the class. In other words, you only have access to the publicy exposed properties that can be set.

Explicitly:

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

    public string CanBeAccessed;
    public string CanBeAccessed2 { set; }
} 
Justin Harvey
  • 14,446
  • 2
  • 27
  • 30
  • The property he's talking about _is_ a public property. – Rawling Aug 08 '12 at 07:54
  • I could have another property `public string PersonId { get; set; }` and I wouldn't be able to access it either. – Adi Lester Aug 08 '12 at 07:57
  • 1
    @Adi Exactly: the reason you can't do this _isn't_ "because you can't access private properties". – Rawling Aug 08 '12 at 07:58
  • @Rawling, I was talking more about the restriction on access to the properties/methods that can be use to set the property with. In other words, you can access properties for 'setting' but not for 'getting'. – Justin Harvey Aug 08 '12 at 08:06
-2

I think that you may be able to solve your problem by backing your properties with private local variables. e.g.

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

Assuming the object initializer sets the properties in the order that you specify them in the initialization code (and it should), the local variables should be accessable (internally by the FullName readonly property).

Kevin
  • 704
  • 3
  • 4