2013-09-23 30 views
2

我有一個非常惱人的錯誤,我的comparer.Compare(x,y)沒有被調用。我有一個IList從數據庫中返回一堆實體,然後對從數據庫返回的每個實體內部的實體列表進行排序。當排序IList時比較器沒有被調用

ie:在這個例子中,每個家庭都有很多賬戶,我想根據賬戶實體的屬性對子列表進行排序。

我打電話邏輯如下:

 List<Household> households = query.ToList(); 
     households.Sort(new HouseholdComparer()); 
     return households; 

,我的比較器看起來像這樣:

public class HouseholdComparer : IComparer<Household> 
{ 
    public int Compare(Household x, Household y) 
    { 
     foreach (Account xAccount in x.Accounts) 
     { 
      foreach (Account yAccount in y.Accounts) 
      { 
       if (xAccount.StartDate == yAccount.StartDate) 
       { 
        if ((xAccount.RevenueT12.HasValue && yAccount.RevenueT12.HasValue) 
         && (xAccount.RevenueT12.Value == yAccount.RevenueT12.Value)) 
        { 
         if ((xAccount.AUAAnnual.HasValue && yAccount.AUAAnnual.HasValue) 
          && (xAccount.AUAAnnual.Value == yAccount.AUAAnnual.Value)) 
          return 0; // all same whatever result 

         if (!xAccount.AUAAnnual.HasValue || !yAccount.AUAAnnual.HasValue) return 0; 
         if (xAccount.AUAAnnual.Value > yAccount.AUAAnnual.Value) return 1; 
         if (xAccount.AUAAnnual.Value < yAccount.AUAAnnual.Value) return -1; 
        } 
        else 
        { 
         if (!xAccount.RevenueT12.HasValue || !yAccount.RevenueT12.HasValue) return 0; 
         if (xAccount.RevenueT12.Value > yAccount.RevenueT12.Value) return 1; 
         if (xAccount.RevenueT12.Value < yAccount.RevenueT12.Value) return -1; 
        } 
       } 
       else 
       { 
        if (x.StartDate > y.StartDate) return 1; 
        if (x.StartDate < y.StartDate) return -1; 
       } 
      } 
     } 
     return 0; // it shouldn't get here 
    } 

當我運行調試我得到的構造,但沒有命中的比較方法,任何人都可以幫忙嗎?

+0

我沒有看到Compare()的任何調用。你是否超載比較操作符? – Paddyd

+2

您是否檢查列表是否爲空或僅包含一個元素?這種情況下不會調用'Compare'方法。 – Douglas

+1

用一個簡短但完整的例子來證明這個問題會更容易診斷。如果列表爲空或者只有一個元素,則不需要調用比較器。 –

回答

0

我知道三種可能原因:

  1. 列表只有一個元素
  2. 列表爲空
  3. 在列表中的所有項目將返回不同的散列碼(GetHashCode的)(即例如如何鮮明作品)
+0

哈希碼與此無關,而且我不知道依賴哈希碼的「獨特」版本。 –

+0

基本上不同的IEnumerable在檢查GetHashCode和Equality by Equals之間的不等式。如果你不相信我 - 這是從相當作者的答案:http://stackoverflow.com/a/5981727/1095750 –

+0

我糾正。 Enumerable.Distinct在內部使用散列表,並且確實使用GetHashCode()來填充散列表。這就是說,兩個項目具有相同的散列碼1)並不會使它們相等,並且2)不能解釋爲什麼比較方法沒有被調用。你的觀點3仍然不正確。 –

-1

看看this example。該方法聲明爲靜態,並直接傳遞給排序調用,而不創建單獨的類。另一種選擇是讓您的Household類實現IComparer接口。然後,您不必將任何內容傳遞給Sort方法,它將使用實現IComparer的Compare方法。

+0

我覺得你很難將IComparer與IComparable混淆。有很多情況下使用比較器比比較好。 –

+0

但是,如果他想創建一個'IComparer',沒有什麼問題,這個答案不能解釋它爲什麼不被調用。 – Servy

+0

@KrisVandermotten我用IComparer ,因爲這是他在例子中使用。這也是MSDN列出的排序功能。 – Vulcronos

0

從我在評論中看到的內容看來,您需要執行IComparer<Account>,沒有這些foreach你知道的循環。

然後,如果AccountsList<Account>,你可以做

Household household = query.First(); 
    household.Accounts.Sort(new AccountComparer()); 
    return household; 

當然,如果Accounts不是List<Account>,你需要一個不同的方法進行排序,但總的想法是相同。

+0

我剛剛想出了相同的解決方案:-)謝謝! – Joshy

0

感謝您的所有輸入傢伙,

我嘗試了一些你的建議和發現最好的一個是排序的家庭內的賬戶,而不是直接去嘗試,並呼籲進行排序家庭排序賬戶。這意味着我不得不改變我的返回類型賬戶是一個列表,然後進行搜索如下:

 //sort the internal Accounts in memory. 
     List<Household> households = query.ToList(); 

     foreach (var household in households) 
      household.Accounts.Sort(Compare); 

     return households; 

的比較程序必須是:

public static int Compare(Account xAccount, Account yAccount) 
    { 
     if (xAccount.StartDate == yAccount.StartDate) 
     { 
      if ((xAccount.RevenueT12.HasValue && yAccount.RevenueT12.HasValue) 
       && (xAccount.RevenueT12.Value == yAccount.RevenueT12.Value)) 
      { 
       if ((xAccount.AUAAnnual.HasValue && yAccount.AUAAnnual.HasValue) 
        && (xAccount.AUAAnnual.Value == yAccount.AUAAnnual.Value)) 
        return 0; // all same whatever result 

       if (!xAccount.AUAAnnual.HasValue || !yAccount.AUAAnnual.HasValue) return 0; 
       if (xAccount.AUAAnnual.Value > yAccount.AUAAnnual.Value) return 1; 
       if (xAccount.AUAAnnual.Value < yAccount.AUAAnnual.Value) return -1; 
      } 
      else 
      { 
       if (!xAccount.RevenueT12.HasValue || !yAccount.RevenueT12.HasValue) return 0; 
       if (xAccount.RevenueT12.Value > yAccount.RevenueT12.Value) return 1; 
       if (xAccount.RevenueT12.Value < yAccount.RevenueT12.Value) return -1; 
      } 
     } 
     else 
     { 
      if (xAccount.StartDate > yAccount.StartDate) return 1; 
      if (xAccount.StartDate < yAccount.StartDate) return -1; 
     } 

     return 0; // it shouldn't get here 
    } 

感謝您的幫助! !