Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 即时窗口和运行时为同一LINQ语句提供不同的结果_C#_Linq - Fatal编程技术网

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

C# 即时窗口和运行时为同一LINQ语句提供不同的结果,c#,linq,C#,Linq,我有一段代码,它只是比较两个集合,并返回一个列表中不属于另一个列表的所有项目 由于这两个列表包含引用不公平的对象,因此我有一个简单的IEquatable来比较它们ID上的对象 我正在运行的代码如下所示: private PreferenceDefinition[] FindUserPreferencesToAdd(PreferenceDefinition[] newDefinitions, PreferenceDefinition[] oldDefinitions) { //Get t

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

由于这两个列表包含引用不公平的对象,因此我有一个简单的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.Whered=>!oldDefinitions.Anydef=>def.Equalsd.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();
}
为什么这样做很好,但第一种方法不行?

看看这里:

如果实现IEquatable,还应该覆盖基 类Object.EqualsObject和GetHashCode的实现,以便 他们的行为与等式的行为一致 方法

您可以清楚地推断==运算符不受实现IEquatable的影响

因此,Equals调用使用自定义的相等方法,而Contains内部使用未被重写的Object.Equals

数组实现ICollection,因此内部使用的Contains方法在带有IndexOf的数组中实现,而不使用尝试使用IEquatable.EQUALES(如果有)的EqualityComparer.Default

尝试添加以下内容:

public override bool Equals(object obj)
{
    var test = obj as Test;

    return test == null ? obj.Equals(this) : Equals(test);
}

您可以在这里看到一个简单的示例:

显示您的IEquatabe实现。@HamletHakobyan它只是公共bool EqualsPreferenceDefinition other{返回this.Id==other.Id;}@plusheen:只是一个旁白,但是您的Equals实现应该优雅地处理other为null的可能性。@sstan啊,是的!我真是目光短浅,thanks@sstan不,没有。你自己测试一下,然后去掉毫无意义的否决票。我错了。我刚刚注意到Enumerable.Contains实现确实利用了IEquatable,但前提是IEnumerable不是ICollection。如果它是一个ICollection,那么它将采用一个不同的路径,其行为与您描述的完全相同。@sstan;但我同意这是误导,没问题;基本上,如果在未实现ICollection的集合上使用Contains,那么它很可能会根据集合的实现而工作。看一下这里的评论:我稍后会尝试找到一个例子。同时,请看第1249行: