views:

176

answers:

3

I am having trouble with, as I said, setting a property's property. Let's say I have a class that represents a transaction. In my class I have a property that represents another class, such as this:

Public Class PersonRecord

    _myPerson = new Person()

    Public Property MyPerson as Person
    Get
        _myPerson = Person.GetAppropriatePerson(Me.PersonID)

        return _myPerson
    End Get

    Set
        _myPerson = value
    End Set
    End Property

So I essentially have a property that has a get filter that gets the appropriate person. The problem is that when I want to set the Person's info through the property, VB seems to ignore that I even did it, such as this:

Me.myPersonRecord.Person.Name = "Some Name"

But when I put a watch on this, after setting the property, my value does not change. I am puzzled by this behavior. Is there something I'm doing wrong? Thanks!

+4  A: 

Every time you do a get .MyPerson, the function Person.GetAppropriatePerson gets called.

I do not know the implementation of that function, but I would guess that it returns a new Person object every time that it is called.

You change the Name of one Person instance. The next time you call .MyPerson, another Person instance gets returned.

Depending on how this is supposed to work, you could do a few things, for instance:

  • Call GetAppropriatePerson in the constructor (if personid is known at that time). Assign the return value to _myPerson, and make the MyPerson property read-only.
  • Or initialize _myPerson to null, then in the MyPerson getter have a if _myPerson == null Then _myPerson = GetAppropriatePerson etc.
codeape
Ah, I see what you're saying. I don't see any way around this, though, unless I remove the getter and just use a function every time I want to get the property's appropriate customer name.
Austin
How about option two above? See the answer by @Dan F for a full example of what your MyPerson property should look like.
codeape
Hey, that worked! I can't believe I didn't think to do the simple if statement to check for a null. Thanks!
Austin
+6  A: 

I don't know if it's a copy n paste error, but you appear to be overwriting _myPerson every time in the Get part of the property. That would more than likely cause your "Some Name" to get overwritten :-)

edit do'h, codeape says the same thing seconds before me :-)

A common pattern for lazy initialisation of properties like this is to do something like the following, which checks if the object is null before overwriting it.

Public Property MyPerson as Person
Get
    If _myPerson Is Nothing Then
        _myPerson = Person.GetAppropriatePerson(Me.PersonID)
    End If
    return _myPerson
End Get

You'd have to change your _myPerson initialisation to be a straight dim _myPerson as Person, rather than dim _myPerson as New Person() too

Dan F
Thanks! I appreciate the help, but codeape just got there first ;) However, it is reassuring that I am using a pattern that I didn't even realize. I always wondered how lazy initialization was used.
Austin
No worries, glad it helped :-)
Dan F
+1  A: 

It must be getting changed by this line: _myPerson = Person.GetAppropriatePerson(Me.PersonID)

step through you code...

eschneider