Search Unity

Why inspecting internal structure of "this->base" may change variable in MSVS?

Discussion in 'Scripting' started by Braza, Feb 3, 2020.

  1. Braza

    Braza

    Joined:
    Oct 11, 2013
    Posts:
    136
    I'm seriously confused by the way MSVS presents things to me regarding my boolean var state.

    There's a button handler that triggers property change:

    GetComponent<Button>().onClick.AddListener(() => purchasableItem.Active = true); 

    purchasableItem is a ScriptableObject;

    Code (CSharp):
    1. public bool Active
    2.         {
    3.             get
    4.             {
    5.                 active = PlayerPrefs.GetInt(PrefName, prePurchased ? 1 : 0) != 0;
    6.                 return active && Purchased;
    7.             }
    8.             set
    9.             {
    10.                 active = value && Purchased;
    11.                 if (active)
    12.                 {
    13.                     foreach(var e in mutuallyExlusiveWith)
    14.                     {
    15.                         e.Active = false;
    16.                     }
    17.                 }
    18.                 PlayerPrefs.SetInt(PrefName, active ? 1 : 0);
    19.                 Raise(active);
    20.             }
    21.         }
    And here's the tricky part for me. When I break at "set", it seems like *active* got equal "true" at line

    active = value && Purchased;


    It even would get into the "true" branch of the condition below if I do not unfold "this->base" variable in MSVS. If I inspect the internal structure of "this->base" then debugger starts showing *active* as false and behaves like it is false.
    What the? truefalse.jpg
     
  2. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    When you expand this->base, Visual Studio tries to display the values of all of your fields and properties. In order for it to know the value of a property, it has to call the "get" function for that property.

    Active.get is changing the value of the field "active" based on your PlayerPrefs, which hasn't yet been updated at the point where you break.

    Having Active.get constantly reset the field "active" to whatever is stored in PlayerPrefs is probably a bad idea. You probably want to read PlayerPrefs once during initialization, and thereafter rely on the local value in the field "active".
     
    Braza and Kurt-Dekker like this.
  3. Braza

    Braza

    Joined:
    Oct 11, 2013
    Posts:
    136
    Wow. Are you saying that Visual Studio actually executes "get" path even though Unity's main thread is on pause? And Unity is meant to be single-threaded, but MSVS does not give a.. care?
    This is madness, but it makes a lot of sense at the same time since the property is actually presented in the inspector and thus must be evaluated.
    I knew that "get" is a mess, but I thought I'd optimize later, so I left it dirty and inefficient. Never thought it would bite me like this.
    Thanks a lot, you've stopped my suffering.
     
  4. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    You can see that Visual Studio is displaying values for your properties. How would it do that without calling get?

    Although properties are technically functions and can theoretically do, well, anything, they're really intended to be used as variables-with-extras. They're supposed to represent something that abstractly behaves "like" a variable, even if they're not implemented as one. So having the abstract logical value change as a result of calling "get" is pretty surprising (both for IDEs and for other programmers).

    But I bet somewhere in Visual Studio's labyrinthine maze of options is some setting that can be used to make it stop displaying properties in the debugger, if you really want.
     
    Braza likes this.
  5. Braza

    Braza

    Joined:
    Oct 11, 2013
    Posts:
    136
    I agree, changing vars in "get" is likely unexpected.