扩展文件比较器,GetHashCode方法

问题描述 投票:0回答:1

我正在尝试扩展文件比较器,以从要比较的文件路径中减去根路径。问题出在GetHashCode()方法中,因为我有两个不同的根路径(root_a和root_b)。如何正确实现将相应的根拍分配给正确的文件?

class FileCompare : System.Collections.Generic.IEqualityComparer<System.IO.FileInfo>
{
    string m_root_a;
    string m_root_b;
    public FileCompare() { }
    public FileCompare(string root_a, string root_b) 
    { 
        m_root_a = root_a; 
        m_root_b = root_b; 
    }

    public bool Equals(System.IO.FileInfo f1, System.IO.FileInfo f2)
    {
        return (f1.FullName.Substring(m_root_a.Length) == 
            f2.FullName.Substring(m_root_b.Length) && 
            f1.Length == f2.Length);
    }

    public int GetHashCode(System.IO.FileInfo fi)
    {
        string s = $"{fi.FullName.Substring(m_root_a.Length)}{fi.Length}";
        return s.GetHashCode();
    }
}

测试比较器的代码:

System.IO.DirectoryInfo dir1 = new System.IO.DirectoryInfo("C:\\Dir Compare Tmp\\dir1\\");
System.IO.DirectoryInfo dir2 = new System.IO.DirectoryInfo("C:\\Dir Compare Tmp\\dir2\\");

IEnumerable<System.IO.FileInfo> list1 = dir1.GetFiles("*.*", 
    System.IO.SearchOption.AllDirectories);
IEnumerable<System.IO.FileInfo> list2 = dir2.GetFiles("*.*", 
    System.IO.SearchOption.AllDirectories);
FileCompare myFileCompare = new FileCompare("C:\\Dir Compare Tmp\\dir1\\", 
    "C:\\Dir Compare Tmp\\dir2\\");

bool areIdentical = list1.SequenceEqual(list2, myFileCompare);

List<string> commonFilesList = new List<string>();
List<string> files1OnlyList = new List<string>();
List<string> files2OnlyList = new List<string>();

var queryCommonFiles = list1.Intersect(list2, myFileCompare);
var queryList1Only = (from file in list1 select file).Except(list2, myFileCompare);
var queryList2Only = (from file in list2 select file).Except(list1, myFileCompare);

foreach (var v in queryCommonFiles)
    commonFilesList.Add(v.FullName);

foreach (var v in queryList1Only)
    files1OnlyList.Add(v.FullName);

foreach (var v in queryList2Only)
    files2OnlyList.Add(v.FullName);

[更新:不幸的是,当我的根路径长度不同时,代码无法正常工作。第二路径C:\\Dir Compare Tmp\\dir2 - Copy\\。我没有在commonFilesList中得到任何文件(从答案中使用GetHashCode实现; Equals函数失败)。有什么解决方案,还是应该使用其他方法比较文件?这将用于比较大量文件,因此代码延迟很重要。

c#
1个回答
1
投票

由于您的比较器已经存储了根路径,并且只希望将那些路径中的文件传递给GetHashCode方法,所以我希望以下实现能够完成您想要实现的目标。

public int GetHashCode(System.IO.FileInfo fi)
    {
        if(fi.FullName.StartsWith(m_root_a))
            return fi.FullName.SubString(m_root_a.Length).GetHashCode();
        else if(fi.FullName.StartsWith(m_root_b))
            return fi.FullName.SubString(m_root_b.Length).GetHashCode();
        else
            throw Exception("Invalid File. This file is not a part of the directories compared.");
    }

更新

基于来自@Rufus的评论

根据CA1065: Do not raise exceptions in unexpected locations中的指定文章它指出

GetHashCode方法:Object.GetHashCodeIEqualityComparer.GetHashCode(Object)方法应该“通常”不引发异常。

  1. GetHashCode应该始终返回一个值。否则,您可能会丢失哈希表中的项目。
  2. 带有参数的GetHashCode版本可以引发ArgumentException。 但是,Object.GetHashCode绝不应该抛出一个例外。

[BUT] >>

如果我正在开发此应用程序,并且要确保

仅比较指定目录中的文件,我肯定会抛出异常。
  • 如果开发人员有意或无意地比较了两个不同文件夹中的文件,而其中一个或两个都没有使用,为什么要初始化该对象,则文件比较完全无效。
  • 此外,GetHashCode方法返回int,而Windows允许uint(4x10 ^ 10)个文件。而且,如果有人(知道吗?)尝试破坏代码,则肯定会发生哈希冲突,从而导致错误匹配。而且我不喜欢这样的机会。
  • 相反,我会丢失哈希表,向用户/开发人员显示错误消息,并要求他/她重新开始。

© www.soinside.com 2019 - 2024. All rights reserved.