2012-07-11 73 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