Reputation: 953
I have the following wrapper class:
public class Wrapper
{
public int Member;
}
In a separate class, I have the following:
public class ContainerClass
{
private Wrapper data;
public Wrapper Property
{
get { return data; }
set { data = value; }
}
public void Foo()
{
Property.Member = 42;
}
}
When Property.Member
is modified in Foo()
, nothing happens (the setter is skipped). However, I can still do the following, for example:
public void Foo()
{
Property = Property;
}
and enter the desired setter. So my question is, why doesn't modifying the member of an object property call that property's setter?
Upvotes: 0
Views: 8048
Reputation: 1
Usually people add an object to a list directly by Add() method which, in turn, does not trigger the setter.
private List<string> _namesList = new List<string>();
// list of names
public List<string> NamesList
{
get
{
return _namesList;
}
set
{
if (value == _namesList)
{
return;
}
_namesList = value;
}
}
In above NamesList property, if you call NamesList.Add("test") it won't invoke setter. Simple solution is store the list in a new variable and gradually set that variable to NamesList e.g.
List<string> lst = new List<string>{ "test1" };
d.NamesList = lst; // setter will fire.
But it's a common mistake to add an object to a list/collection directly. :)
Upvotes: 0
Reputation: 148980
Because you aren't setting the value of Property
. Your code just invokes the getter of Property
, then setting the value of the Member
field (which would invoke the setter of Member
if it were a property, which isn't the case here).
If you want to execute code when Member
is set, you need to have
public class Wrapper
{
private int member;
public int Member
{
get { return this.member; }
set
{
this.member = value;
DoSomething();
}
}
}
Or perhaps a more elegant solution would be to use events. The built-in INotifyProperyChanged interface gives you a pretty good template for this sort of thing.
using System.ComponentModel;
public class Wrapper : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private int member;
public int Member
{
get { return this.member; }
set
{
this.member = value;
this.OnPropertyChanged("Member");
}
}
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
public class ContainerClass
{
private Wrapper data;
public Wrapper Property
{
get { return data; }
set { data = value; }
}
public void Foo()
{
data.PropertyChanged += data_PropertyChanged;
Property.Member = 42;
}
private void data_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Member")
{
DoStuff();
}
}
}
Upvotes: 2
Reputation: 65049
Because you aren't modifying the reference. You are modifying the reference' member.
Say, for example, if I were to stand you in the corner of the room and say, "Hold this apple". If I come in and switch the apple with a banana.. I haven't switched you, so you're happy. But if I switch you out with someone else you'll complain that I'm replacing you.
..that is my analogy for this anyway.
Also, you've prefixed a class with I
.. this is generally used on interfaces in .NET land..
EDIT: I realise that if I were to stand you in a corner holding a piece of fruit.. you probably wouldn't complain when I replaced you..
Upvotes: 3
Reputation: 5464
In the constructor of foo, you are setting the field of class Wrapper.
public void Foo()
{
Property.Member = 42; // No property set, you are accessing a field.
}
In the second example, you are setting a property
public void Foo()
{
// Setting Property "Property" to the value of "Property"
// You should see both the getter and the setter called.
Property = Property;
}
I do not know what you are attempting to do, but maybe you wanted Wrapper to have a property too.
public class Wrapper
{
private int member;
public int Member
{
get { return data; }
set { data = value; }
}
}
Then the setter would be called on Wrapper.Member when you did Property.Member = 42
Upvotes: 0