DependencyObject плохо обрабатывает равенство свойств объекта - PullRequest
0 голосов
/ 29 октября 2018

Я столкнулся с StackOverflowException, из-за которого я обнаружил, что DependencyObject неправильно обрабатывает равенство?!

Когда свойство DependencyProperty имеет тип Object, оно всегда будет использовать Reference.Equals. Это заставляет каждый раз вызывать PropertyChanged для строк и типов значений, когда применяется одно и то же значение.

Если вы посмотрите на

DependencyObject.Equals (DependencyProperty dp, значение объекта 1, объект значение2)

https://referencesource.microsoft.com/#WindowsBase/Base/System/Windows/DependencyObject.cs,3453

/// <summary>
///     Helper method to compare two DP values
/// </summary>
private bool Equals(DependencyProperty dp, object value1, object value2)
{
    if (dp.IsValueType || dp.IsStringType)
    {
        // Use Object.Equals for Strings and ValueTypes
        return Object.Equals(value1, value2);
    }
    else
    {
        // Use Object.ReferenceEquals for all other ReferenceTypes
        return Object.ReferenceEquals(value1, value2);
    }
}

Простой способ воспроизвести:

public static readonly DependencyProperty ObjValueProperty = DependencyProperty.Register(nameof(ObjValue), typeof(object), typeof(MainWindow), new PropertyMetadata(default(object)));

public object ObjValue
{
    get
    {
        return GetValue(ObjValueProperty);
    }
    set
    {
         SetValue(ObjValueProperty, value);
    }
}

protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
    if(e.Property == ObjValueProperty) { /*Breakpoint here*/ }
}

...
ObjValue = 7;
ObjValue = 7;

Итак, это желаемое поведение или ошибка?

1 Ответ

0 голосов
/ 30 октября 2018

Я не думаю, что это ошибка. Это просто способ, которым dotnet обрабатывает объекты. То же самое, если вы попробуете это без контекста DependencyProperties:

Я создал небольшое консольное приложение:

object v1 = 7;
object v2 = 7;
if (v1 == v2) Console.Write("are the same"); else Console.Write("are different");

Я прочитал "разные" в консоли. Поэтому, как правило, если объекты оцениваются на равенство, то всегда с помощью ReferenceEquals (даже если они являются типами значений в штучной упаковке).

...