3

我在复合控件中有一个属性,用于在实际设置相关的私有字段并执行其他一些操作之前检查值是否已更改。

但是,它似乎从未评估过该声明。

这是该属性的代码:

public T SearchCriteria
        {
            get
            {
                return mySearchCriteria;
            }
            set
            {
                if (value != mySearchCriteria)
                {
                    mySearchCriteria = value;
                    EnsureChildControls();
                    SearchGridParser parser = SearchGridParserFactory.GetParser(this.Type);
                    parser.SetSearchPanelControls<T>(this.mySearchCriteria, ref mySearchParametersPanel);
                    GridView.PageIndex = 0;
                }
            }
        }

我已经单步执行了代码,每次到达“value != mySearchCriteria”时,它都会评估为 false 并跳过 if 语句中的代码。事实上,即使我将其更改为“value == mySearchCriteria”,它也会这样做。如果只是完全跳过它,无论它如何评估!

什么嘿?

我尝试更改检查中参数的顺序,并使用 object.Equals() 但这些更改都没有任何区别。

我已经覆盖了 Equals、!=、== 和 GetHashCode。

在代码中的其他地方,它对这些对象类型使用“==”和“!=”没有问题,所以我知道我的覆盖工作正常。

问题是,这甚至不会触及被覆盖的方法。我在 "=="、"!="、"Equals" 和 "GetHashCode" 上放置了中断,并且在评估 "value != mySearchCriteria" 语句时没有调用它们。

就像它完全跳过评估它一样。

4

1 回答 1

4

在泛型类型之间使用 == 几乎总是一个坏主意。运算符是重载的,而不是被覆盖的,所以即使你的实际类型上有 == 运算符,编译器也不会知道它。(这意味着您声称您已经“覆盖”==并且!=已经不正确 - 您已经重载了这些运算符。您应该确保您了解差异,因为它非常重要。)

当你写:

在代码中的其他地方,它对这些对象类型使用“==”和“!=”没有问题,所以我知道我的覆盖工作正常。

我怀疑这些区域不在通用代码中......它们是编译器知道正在比较什么类型的地方,所以知道使用你的重载。这与您的一般情况非常不同,在这种情况下,编译器知道 == 使用什么,所以回退到引用标识。

我假设您有一个通用约束,where T : class或者您的代码根本无法编译 - 但它仍然只是执行参考比较,而不是使用T.

用于使用包括EqualityComparer.Default<T>.Equals(value, mySearchCriteria)的覆盖实现。EqualsIEquatable<T>

于 2010-11-08T15:29:08.137 回答