5

I have a property ggFileName defined like this:

    private string _ggFileName = "";
    public string ggFileName
    {
        get 
        { 
            return _ggFileName;
        }
        set 
        {
            _ggFileName = value;
            ReadXmlSchemaFromFile();
        }
    }

When assinging a value to ggFileName, the method ReadXmlSchemaFromFile(); is called. So far so good.

My problem is that when I assign the property ggFileName with the same value it already contains, nothing happens. The setter is not called until I assign it a different value.

I agree that in almost every case this is perfectly logical, but in my case it raises a problem. What if the file in ggFileName is changed outside my application ? Assigning the same file again to ggFileName does not calls my setter, so ReadXmlSchemaFromFile() is also not called. So now I have to set a dummy file to property ggFileName and than assign the same file again to ggFileName to get it working.

C# seems to be wanting to help me by not calling the setter when assigning the same value, how can I tell c# to stop helping me ?

I did not know that c# did this, in all my setters I have code like this: if (value != _myValue) { do setter logic here } I guess that I do not need to write that check anymore than ?

Just to make things more clear as people do not seem to understand my question. 1. My setter does get called, but only when assigning a different value 2. I do not want to use a method, because after setting the property I want some checks to be done and I do not want any other user of my class to be able to bypas that check. that is what properties are for, or not ? 3. The code that assignes a value I cannot post. It is a property of a custom control and it is called by the designer by editing the object inspector. Again, it works as long as I keep feeding it different values

thanks

GuidoG
  • 11,359
  • 6
  • 44
  • 79
  • 1
    I think it is bad idea to do this in a setter. Why don't you add a method? – zsf222 May 23 '14 at 12:02
  • 2
    Can you post the code that actually *calls* the setter? – nvoigt May 23 '14 at 12:02
  • Agree that this sort of behavior is bad practice in properties. Use a method. – DonBoitnott May 23 '14 at 12:03
  • 1
    You're not assigning a value to your field, you're assigning a reference. Why would you think your app's private data can be changed by some 3rd party program? – Tarec May 23 '14 at 12:03
  • The purpose of a property is to allow users of your class to set a private value, and to be able to execute code on setting that value. So using a method instead breaks the rule that when the value is set, some code has to be executed. That is why a property is used and not a method – GuidoG May 23 '14 at 12:04
  • The property is a string that holds the path+ filename to a file. So yes it is very very very possible the file is changed outside my application. Also the setter is called when I assign it a new value, not when assigning it the same value again. That is exactly my question – GuidoG May 23 '14 at 12:08
  • @David I tried a messagebox as the first line in the setter. It only appears when I assign a differnt value to the property, not when assigning the same value. So in my visual studio 2012 it appears to be working so, also in this article http://msdn.microsoft.com/en-us/library/w86s7x04.aspx it is explained that a setter is called when a new value is assigned. – GuidoG May 23 '14 at 12:13

3 Answers3

32

For what it is worth - I came across this problem and in our codebase it was down to Fody.

Fody inserts an equality check and short circuits the setter. I didn't really expect your problem to be down to Fody (because of your mention of the visual designer). I thought it might be of value to others who come across this post as I did.

I used dotPeek to find the code being inserted.

For your benefit I used dotPeek to inspect the winforms PropertyGrid and found the code snippet below. The visual studio may well be different but I strongly suspect it is doing something similar. If you are really keen you could log a call stack when you set a different value. Somewhere in that call stack would be the function with the equality check.

private object SetPropertyValue(object obj, object objVal, bool reset, string undoText)
{
  DesignerTransaction designerTransaction = (DesignerTransaction) null;
  try
  {
    object propertyValueCore = this.GetPropertyValueCore(obj);
    if (objVal != null && objVal.Equals(propertyValueCore)) // if equal return!!!!
      return objVal;
    this.ClearCachedValues();

About Fody:

This technique of "weaving" in new instructions is fantastically powerful. You can turn simple public properties into full INotifyPropertyChanged implementations, add checks for null arguments, add Git hashes to your Assemblies, even make all your string comparisons case insensitive.

Worth noting it can be disabled with [DoNotCheckEquality].

David Hollinshead
  • 1,710
  • 17
  • 18
  • What is Fody ? As I tried to describe above the problem is in the visual designer of visual studio. When you assign the same value to a property in code the setter will be called each time, but when you assign the same value to a property using the object inspector, the setter is not called. In that case the setter is only called when giving it another value. – GuidoG Sep 18 '14 at 17:51
  • I had the same problem, and it was with a class that didn't implement the PropertyChanged attribute, the solution was to remove fody from the project. Thanks :) – Rafael Mar 03 '15 at 00:23
  • Thank you for mentioning Fody. Someone else included Fody in our project, and I could not figure out why the setter wasn't being called! – LightStruk Jun 02 '15 at 18:06
  • 1
    wow... I just spent 2 hours trying to figure out this crazy behavior... Thank you! – Maverick Meerkat Apr 29 '18 at 12:33
  • For more information on fody configuration on this behavior (like not checking for the hole projet) : https://stackoverflow.com/a/39837809/1866828 – dperez May 29 '20 at 19:09
3

The problem is in the buggy designer from visual studio. When setting a property value using the "property windows" in designtime, this window does not set the value for you property when its the same value already in there.

When doing this in code there is no problem, than the value will be set no matter what.

This is another fine example how microsoft tries to help you (all be it helping you backwards in stead of forwards...)

hirogen
  • 71
  • 2
0

I had the same issue today with a file name property in a properyGrid. I found a simple workaround that is patchy but it is good for me. Instead of returning the _ggFileName in the getter, I returned "Browse File" I made sure I don't use the getter but use the field instead

So basically the only one that uses the getter is the propery grid, of course it's not good programming, but it solved the problem for me quickly.

private string _ggFileName = "";
public string ggFileName
{
    get 
    { 
        return "Browze File";
    }
    set 
    {
        _ggFileName = value;
        ReadXmlSchemaFromFile();
    }
}
Denny Ferrassoli
  • 1,763
  • 3
  • 21
  • 40