2012-07-11 70 views
0

我正在尝试创建一个SortedDictionary,其中的键是一个表示文件/文件夹路径的字符串。我正在尝试根据路径深度对该字典进行排序。我的标准只是检查每个路径中斜线的数量,并在字典的开头放置斜线最多的路径。IComparer和SortedDictionary可能存在的问题

我的问题是,我不能检测到一些奇怪的问题,字典可以有多个完全相同的键。经过几个小时的调试后,问题似乎是:“有时”我的IComparer实现不调用ContainsKey方法或将新值添加到字典时,字典中的所有条目都会循环。我没有得到任何例外或任何东西。

这是我的代码。(它有点只要):

namespace ConsoleApplication1 
{ 

    class DepthComparer : IComparer<string> 
    { 
     public int Compare(string X, string Y) 
     { 
      //Sort From deepest to shallowest 
      //C:\Users\NAME\Desktop\Folder\ should precede C:\Users\NAME\Desktop\ 
      //Paths with same root level are ignored 

      int nXSlashes = SlashCounter(X); 
      int nYSlashes = SlashCounter(Y); 

      if (string.Compare(X, Y, true) == 0) //same path 
      { 
       return 0; 
      } 

      //Put Deepest Path at the beginning 
      return (nXSlashes > nYSlashes ? -1 : 1); 

     } 

     public int SlashCounter(string stPath) 
     { 
      int nSlashes = 0; 
      for (int i = 0; i < stPath.Length - 1; ++i) 
      { 
       if (stPath[i] == ('/') || stPath[i] == ('\\')) 
        nSlashes++; 
      } 
      return nSlashes; 
     } 
    } 

    public class ScanOptions 
    { 
     public enum ExcludeRule 
     { 
      Invalid = 0x00, 
      File = 0x01, 
      Folder = 0x02, 
      FileFolder = File | Folder, 
     } 

     private SortedDictionary<string, ExcludeRule> _dExcludedPaths; 

     public ScanOptions() 
     { 
      _dExcludedPaths = null;    
     } 

     //Creates a new Excluded Paths List (Automatically clears the current list if its already initialized) 
     public void CreateExcludedPathsList() 
     { 
      if (_dExcludedPaths == null) 
       _dExcludedPaths = new SortedDictionary<string, ExcludeRule>(new DepthComparer()); 
      else 
       ClearExcludedPathsList(); 
     } 

     public void ClearExcludedPathsList() 
     { 
      _dExcludedPaths.Clear(); 
     } 

     public bool IsExcludedPathsListInitialized() 
     { 
      return _dExcludedPaths != null ? true : false; 
     } 

     public void AddExcludePath(string stPath, ExcludeRule Rule) 
     { 
      if (!IsExcludedPathsListInitialized()) 
       return; 

      if (string.IsNullOrEmpty(stPath) || Rule == ExcludeRule.Invalid) 
       return; 

      string stTmp = stPath.ToLower(); 
      try 
      { 
       if (stTmp.EndsWith("\\")) 
       { 
        stTmp = stTmp.Remove(stTmp.Length - 1); 
       } 

       if (_dExcludedPaths.ContainsKey(stTmp)) 
       { 
        ExcludeRule OldRule = ExcludeRule.Invalid; 
        if (_dExcludedPaths.TryGetValue(stTmp, out OldRule)) 
        { 
         if ((OldRule & Rule) == 0) 
          _dExcludedPaths[stTmp] |= Rule; //Same path new rule, append rule to existing one 
        } 
        return; 
       } 
       else 
       { 
        //brand new entry 
        _dExcludedPaths[stTmp] = Rule; 
       } 
      } 
      catch 
      { 

      } 
     } 

     public void AddExcludePaths(List<string> ExcludePaths, ExcludeRule Rule) 
     { 
      if (!IsExcludedPathsListInitialized()) 
       return; 

      foreach (string stPath in ExcludePaths) 
       AddExcludePath(stPath, Rule); 
     } 

     public void AddExcludePaths(SortedDictionary<string, ExcludeRule> ExcludePaths) 
     { 
      if (!IsExcludedPathsListInitialized()) 
       return; 

      foreach (KeyValuePair<string, ExcludeRule> PathRule in ExcludePaths) 
       AddExcludePath(PathRule.Key, PathRule.Value); 
     } 


     public void ShowInConsole() 
     { 
      foreach (KeyValuePair<string, ScanOptions.ExcludeRule> Rule in _dExcludedPaths) 
      { 
       Console.WriteLine(Rule.Key + "\t" + Rule.Value); 
      } 
     } 

    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 

      string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); 

      //Fill a new string list with some paths 
      List<string> ExcludedPaths = new List<string>(); 
      string ExPath = desktopPath + "\\12345678\\"; 
      ExcludedPaths.Add(ExPath); 
      ExPath = desktopPath + "\\abcdefg\\"; 
      ExcludedPaths.Add(ExPath); 
      ExPath = desktopPath + "\\ABCDEFG\\"; 
      ExcludedPaths.Add(ExPath); 
      ExPath = desktopPath + "\\1A2B3C 4D5E6F\\123456\\4567896\\"; 
      ExcludedPaths.Add(ExPath); 
      ExPath = desktopPath + "\\CDEVQWER ASD\\456786\\"; 
      ExcludedPaths.Add(ExPath); 

      //Create the exclude list object 
      ScanOptions scanOpt = new ScanOptions(); 
      scanOpt.CreateExcludedPathsList(); 

      //First manually add one of the paths from the list above 
      scanOpt.AddExcludePath(desktopPath + "\\12345678\\", ScanOptions.ExcludeRule.Folder); 

      //Now add the whole list of paths to the exclude list in scan options 
      scanOpt.AddExcludePaths(ExcludedPaths, ScanOptions.ExcludeRule.Folder); 

      //Now add the first entry a couple more times with different value each time 
      scanOpt.AddExcludePath(desktopPath + "\\12345678\\", ScanOptions.ExcludeRule.File); 

      scanOpt.AddExcludePath(desktopPath + "\\12345678\\", ScanOptions.ExcludeRule.Folder); 


      //Dump the list to console 
      //We now have two keys in the dictionary that equal desktopPath + "\\12345678\\" 
      scanOpt.ShowInConsole(); 

     } 
    } 
} 

在主要结束()_dExcludedPaths将有两个键它正好彼此相等的。

有人可以帮助理解这里发生了什么,以及如何有可能在字典中重复键?

感谢

回答

1
public int Compare(string X, string Y) 
    { 
     int nXSlashes = SlashCounter(X); 
     int nYSlashes = SlashCounter(Y); 

     if (nXSlashes > nYSlashes) 
      return -1; 
     if (nXSlashes < nYSlashes) 
      return 1; 

     return string.Compare(X, Y, true);   
    } 
+0

它的工作..但你能解释这是怎么从我实现不同??? – 2012-07-11 07:43:15

+0

@RedSerpent原始版本不是可交换函数:cmp(x,y)!= -cmp(y,x) – 2012-07-11 08:36:44

+0

谢谢,我还想知道为什么字典有两次列出相同的密钥?我认为这应该会导致例外.. – 2012-07-11 08:56:30