即时窗口和运行时为同一 LINQ 语句提供不同的结果



我有一段代码,它只是比较两个集合,并返回一个列表中不属于另一个列表的所有项目。

由于这两个列表包含引用不公平的对象,因此我有一个简单的IEquatable来比较其 ID 上的对象。

我正在运行的代码如下:

private PreferenceDefinition[] FindUserPreferencesToAdd(PreferenceDefinition[] newDefinitions, PreferenceDefinition[] oldDefinitions)
{
     //Get the newly selected definitions
     var newPreferences = newDefinitions.Where(def => def.IsSelected);
     //Get all new definitions that don't exist in the old list
     var preferencesToAdd = newPreferences.Where(def => !oldDefinitions.Contains(def)).ToArray();
     return preferencesToAdd;
}

preferencesToAdd的结果给了我完全相同的newPreferences列表,尽管故意确保newDefinitions包含已选择的其他项目。如果我传入 7 个新首选项,它将返回 7 个首选项以"添加" - 一个不正确的实现。

但是,当我在

返回时遇到断点时,当我在即时窗口中运行完全相同的 LINQ 语句时,它给了我:

newPreferences.Where(def => !oldDefinitions.Contains(def)).ToArray();
{App1Test.PreferenceDefinition[1]}
    [0]: {App1Test.PreferenceDefinition}

这包含应添加的单个结果。

为什么即时窗口会给我正确的结果,而运行时代码不会?我尝试在运行时 LINQ 查询运行之前和之后在即时窗口中运行此语句,以确保它不是操作顺序,但它没有区别。

编辑:

我找到了解决问题的方法,将第二个 LINQ 语句替换为:

var preferencesToAdd = newPreferences.Where(d => !oldDefinitions.Any(def => def.Equals(d))).ToArray();

但是我不明白为什么原版不起作用。我有一个非常相似的场景,它与我在这里尝试实现的目标相反(查找要删除的项目),并且工作正常。我错过了什么吗?

编辑 2:

即使没有IEquatable,这段代码也能正常工作:

private PreferenceDefinition[] FindUserPreferencesToDelete(PreferenceDefinition[] newDefinitions, PreferenceDefinition[] oldDefinitions)
{
    //Get the newly selected definitions
     var newPreferences = newDefinitions.Where(def => def.IsSelected);
     //Get all old definitions that don't exist in this new list
     var preferencesToDelete = oldDefinitions.Where(def => !newPreferences.Contains(def));
     return preferencesToDelete.ToArray();
}

为什么这很好,但第一种方法不能?

看看这里:

https://msdn.microsoft.com/en-us/library/ms131187(v=vs.110).aspx

如果实现 IEquatable,则还应覆盖基础 Object.Equals(Object) 和 GetHashCode 的类实现,以便 它们的行为与 IEquatable.Equals 的行为一致。 方法。

可以明确推断出 == 运算符不受实现 IEquatable 的影响;

因此,Equals 调用使用自定义相等方法,而 Contains 在内部使用 Object.Equals,它不会被重写。

该数组实现 ICollection,因此内部使用的 Include 方法是使用 IndexOf 在数组中实现的,而不使用 EqualityComparer.Default,它尝试使用 IEquatable.Equals(如果有的话)。

尝试添加以下内容:

public override bool Equals(object obj)
{
    var test = obj as Test;
    return test == null ? obj.Equals(this) : Equals(test);
}

您可以在此处看到一个简单的示例:https://dotnetfiddle.net/C5R4bE

相关内容

  • 没有找到相关文章

最新更新