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

时间:2016-07-12 11:49:01

标签: c# 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();
}

为什么这样可行,但第一种方法不会?

1 个答案:

答案 0 :(得分:2)

看看这里:

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

  

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

您可以明确地推断 == 运算符不受实施 IEquatable ;

的影响

因此,等于调用使用您的自定义相等方法,包含在内部使用未被覆盖的 Object.Equals

数组实现 ICollection 因此内部使用的包含方法在 IndexOf 的数组中实现,而不使用 EqualityComparer.Default < / strong>试图使用 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