Linq 确定两个项目列表的特定属性之间是否存在差异的最有效方法?
在C#.NET 4.0中,我正在努力找到最有效的方法来确定两个项目列表的内容是否包含任何差异 我不需要知道差异是什么,只要根据我的标准判断列表是否不同即可 我试图比较的两个列表包含FileInfo对象,我只想比较每个项目的FileInfo.Name和FileInfo.LastWriteTimeUtc属性。所有FileInfo项目都是针对位于同一目录中的文件,因此FileInfo.Name值将是唯一的 总而言之,我正在寻找以下条件的单一布尔结果:Linq 确定两个项目列表的特定属性之间是否存在差异的最有效方法?,linq,c#-4.0,Linq,C# 4.0,在C#.NET 4.0中,我正在努力找到最有效的方法来确定两个项目列表的内容是否包含任何差异 我不需要知道差异是什么,只要根据我的标准判断列表是否不同即可 我试图比较的两个列表包含FileInfo对象,我只想比较每个项目的FileInfo.Name和FileInfo.LastWriteTimeUtc属性。所有FileInfo项目都是针对位于同一目录中的文件,因此FileInfo.Name值将是唯一的 总而言之,我正在寻找以下条件的单一布尔结果: ListA是否包含任何FileInfo.Name不
Kyle这不是最有效的方法(在快速和肮脏类别中可能排名第4位): 说明:
匿名类是通过属性值进行比较的,这正是您想要做的,这导致我考虑沿着这些线进行LINQ投影 p.S.
您应该仔细检查语法,我只是在没有编译器的情况下快速完成了此任务。我将使用自定义的
IEqualityComparer
来完成此任务:
public class FileNameAndLastWriteTimeUtcComparer : IEqualityComparer<FileInfo>
{
public bool Equals(FileInfo x, FileInfo y)
{
if(Object.ReferenceEquals(x, y)) return true;
if (x == null || y == null) return false;
return x.FullName.Equals(y.FullName) && x.LastWriteTimeUtc.Equals(y.LastWriteTimeUtc);
}
public int GetHashCode(FileInfo fi)
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
hash = hash * 23 + fi.FullName.GetHashCode();
hash = hash * 23 + fi.LastWriteTimeUtc.GetHashCode();
return hash;
}
}
}
公共类文件名和LastWriteTimeutcComparer:IEqualityComparer
{
公共bool等于(FileInfo x,FileInfo y)
{
if(Object.ReferenceEquals(x,y))返回true;
如果(x==null | | y==null)返回false;
返回x.FullName.Equals(y.FullName)和&x.LastWriteTimeUtc.Equals(y.LastWriteTimeUtc);
}
public int GetHashCode(FileInfo-fi)
{
未选中//溢出很好,只需换行
{
int hash=17;
hash=hash*23+fi.FullName.GetHashCode();
hash=hash*23+fi.LastWriteTimeUtc.GetHashCode();
返回散列;
}
}
}
现在,您可以将哈希集
与此比较器一起使用,并且:
var comparer=new filename和lastWriteTimeutcComparer();
var uniqueFiles1=新哈希集(列表1,比较器);
bool anyDifferences=!uniqueFiles1.SetEquals(列表2);
请注意,我使用了FileInfo.FullName
而不是Name
,因为名称根本不是unqiue
旁注:另一个优点是,您可以将此比较器用于许多LINQ方法,如
GroupBy
,Except
,Intersect
或Distinct
,这看起来像是的副本,再加上使用自定义的IComparer。FileInfo.Name
不是唯一的,您考虑过吗?因此,这两个列表中的名称可能会在不同的时间出现多次。这适用于你的第三个标准。您是指FullName
属性吗?@TimSchmelter正在比较的FileInfo项用于同一目录中的文件,因此在这种情况下FileInfo.Name将是唯一的。我已经更新了我的问题以澄清这一点。@KyleK:最好还是使用全名
,以防将来包含子目录(或其他目录)。
public class FileNameAndLastWriteTimeUtcComparer : IEqualityComparer<FileInfo>
{
public bool Equals(FileInfo x, FileInfo y)
{
if(Object.ReferenceEquals(x, y)) return true;
if (x == null || y == null) return false;
return x.FullName.Equals(y.FullName) && x.LastWriteTimeUtc.Equals(y.LastWriteTimeUtc);
}
public int GetHashCode(FileInfo fi)
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
hash = hash * 23 + fi.FullName.GetHashCode();
hash = hash * 23 + fi.LastWriteTimeUtc.GetHashCode();
return hash;
}
}
}
var comparer = new FileNameAndLastWriteTimeUtcComparer();
var uniqueFiles1 = new HashSet<FileInfo>(list1, comparer);
bool anyDifferences = !uniqueFiles1.SetEquals(list2);