{"action":"opened","issue":{"url":"https://api.github.com/repos/dotnet/corefx/issues/13831","repository_url":"https://api.github.com/repos/dotnet/corefx","labels_url":"https://api.github.com/repos/dotnet/corefx/issues/13831/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/corefx/issues/13831/comments","events_url":"https://api.github.com/repos/dotnet/corefx/issues/13831/events","html_url":"https://github.com/dotnet/corefx/issues/13831","id":190544369,"number":13831,"title":"ExpandoObject PropertyChanged event fails to detect changes in value types","user":{"login":"JackUkleja","id":4020612,"avatar_url":"https://avatars.githubusercontent.com/u/4020612?v=3","gravatar_id":"","url":"https://api.github.com/users/JackUkleja","html_url":"https://github.com/JackUkleja","followers_url":"https://api.github.com/users/JackUkleja/followers","following_url":"https://api.github.com/users/JackUkleja/following{/other_user}","gists_url":"https://api.github.com/users/JackUkleja/gists{/gist_id}","starred_url":"https://api.github.com/users/JackUkleja/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JackUkleja/subscriptions","organizations_url":"https://api.github.com/users/JackUkleja/orgs","repos_url":"https://api.github.com/users/JackUkleja/repos","events_url":"https://api.github.com/users/JackUkleja/events{/privacy}","received_events_url":"https://api.github.com/users/JackUkleja/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2016-11-20T07:30:30Z","updated_at":"2016-11-20T07:30:30Z","closed_at":null,"body":"`ExpandoObject` uses a `IDictionary<string, object>` under the hood for storing properties. It also implements `INotifyProperyChanged` such that when the value for a property changes (but only when it changes) it will raise the `PropertyChanged` event - i.e. the normal INPC pattern.\r\n\r\nThe problem is this does not work for value types - the `PropertyChanged` event is raised every time a value type property is set, _regardless of whether the value has changed_.\r\n\r\nThe problem is due to the code which deals with setting the property value `TrySetValue` which takes an `object` as the parameter type for the value. This forces value types to be boxed when passed in, and then the equality operator `!=` is used to check if the value has changed - but for two `int`s which have been boxed into an `object` this operator is always going to return `true`. \r\n\r\n```csharp\r\n           // Notify property changed, outside of the lock.\r\n            var propertyChanged = _propertyChanged;\r\n            if (propertyChanged != null && value != oldValue) {\r\n                // Use the canonical case for the key.\r\n                propertyChanged(this, new PropertyChangedEventArgs(data.Class.Keys[index]));\r\n            }\r\n```\r\n\r\nI think the code should be:\r\n\r\n```csharp\r\n           // Notify property changed, outside of the lock.\r\n            var propertyChanged = _propertyChanged;\r\n            if (propertyChanged != null && !value.Equals(oldValue)) {\r\n                // Use the canonical case for the key.\r\n                propertyChanged(this, new PropertyChangedEventArgs(data.Class.Keys[index]));\r\n            }\r\n```"}}
{"actor":{"display_login":"JackUkleja"}}