gpt4 book ai didi

c# - System.Linq.Enumerable+WhereSelectArrayIterator 与 List 上的 IEnumerable.Except()

转载 作者:太空宇宙 更新时间:2023-11-03 20:51:10 25 4
gpt4 key购买 nike

也许我在这里遗漏了细节,但我希望 IEnumerable.Except() 可以在 Enumerables 上工作,而不是具体地转换为集合。

让我用一个简单的例子来解释:我有一个目录中的文件列表,我想排除以某个字符串开头的文件。

var allfiles = Directory.GetFiles(@"C:\test\").Select(f => new FileInfo(f));

同时获得匹配和不匹配的文件将是识别两个集合之一然后在完整列表上进行 .Except() 处理的问题,对吧?

var matching = allfiles.Where(f => f.Name.StartsWith("TOKEN"));

var notmatching = allfiles.Except(matching, new FileComparer());

其中 FileComparer() 是比较两个文件的完整路径的某个类。

好吧,除非我将这三个集合都转换为一个列表,否则最后一个不匹配的变量仍然会在我对匹配集合执行 .Except() 之后为我提供完整的文件列表。明确一点:

var allfiles = Directory.GetFiles(@"C:\test\").Select(f => new FileInfo(f));
var matching = allfiles.Where(f => f.Name.StartsWith("TOKEN"));
var notmatching = allfiles.Except(matching, new FileComparer());

不排除,而

var allfiles = Directory.GetFiles(@"C:\test\").Select(f => new FileInfo(f)).ToList();
var matching = allfiles.Where(f => f.Name.StartsWith("TOKEN")).ToList();
var notmatching = allfiles.Except(matching, new FileComparer()).ToList();

实际上是按照锡 jar 上所说的去做。我在这里错过了什么?我不明白为什么 LINQ 不操作当前未转换为列表的集合。

例如,在第一种情况下甚至不会调用 FileComparer。

internal class FileComparer : IEqualityComparer<FileInfo>
{
public bool Equals(FileInfo x, FileInfo y)
{
return x == null ? y == null : (x.Name.Equals(y.Name, StringComparison.OrdinalIgnoreCase) && x.Length == y.Length);
}

public int GetHashCode(FileInfo obj)
{
return obj.GetHashCode();
}
}

最佳答案

两者之间的区别在于,如果没有 ToList,延迟的 allfiles 查询会执行两次,从而生成不同的 FileInfo 实例,这些实例不会传递引用相等性。

你的 FileComparer implements GetHashCode incorrectly ,因为它只是返回 FileInfo 对象的基于引用的哈希码(它本身不会覆盖 GetHashCode)。

Implementations are required to ensure that if the Equals(T, T) method returns true for two objects x and y, then the value returned by the GetHashCode(T) method for x must equal the value returned for y.

解决方案是根据与Equals相同的相等性定义来实现GetHashCode:

public int GetHashCode(FileInfo obj)
{
return StringComparer.OrdinalIgnoreCase.GetHashCode(obj.Name);
}

关于c# - System.Linq.Enumerable+WhereSelectArrayIterator 与 List<T> 上的 IEnumerable.Except(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55179571/

25 4 0