在Linq OrderBy中使用自己的IComparer <T>

我有一个通用的

List<MyClass> 

其中MyClass有一个属性InvoiceNumber ,它包含如下的值:

一分之二十零万零九百零六
二分之二十零万零九百零六
..
十分之二十零万〇九百〇六
十一分之二十零万零九百零六
十二分之二十万○九百○六

我的清单是绑定到一个

 BindingList<T> 

它支持用linq进行sorting:

 protected override void ApplySortCore( PropertyDescriptor property, ListSortDirection direction) { _sortProperty = property; _sortDirection = direction; var items = this.Items; switch (direction) { case ListSortDirection.Ascending: items = items.OrderByDescending(x => property.GetValue(x)).ToList(); break; case ListSortDirection.Descending: items = items.OrderByDescending(x => property.GetValue(x)).ToList(); break; } this.Items = items; } 

然而,默认的比较器sorting(如假设)是这样的:

一分之二十零万零九百零六
十分之二十零万〇九百〇六
十一分之二十零万零九百零六
十二分之二十万○九百○六
二分之二十零万零九百零六

这在这种情况下是讨厌的。

现在我想用我自己的IComparer<T> 。 它看起来像这样:

 public class MyComparer : IComparer<Object> { public int Compare(Object stringA, Object stringB) { String[] valueA = stringA.ToString().Split('/'); String[] valueB = stringB.ToString().Split('/'); if(valueA .Length != 2 || valueB .Length != 2) return String.Compare(stringA.ToString(), stringB.ToString()); if (valueA[0] == valueB[0]) { return String.Compare(valueA[1], valueB[1]); } else { return String.Compare(valueA[0], valueB[0]); } } } 

并更改了ApplySortCore代码以使用此IComparer

 case ListSortDirection.Ascending: MyComparer comparer = new MyComparer(); items = items.OrderByDescending( x => property.GetValue(x), comparer).ToList(); break; 

当我debugging我的代码时,我看到MyComparer.Compare(object, object)被多次调用,并为比较方法返回正确的值(-1,0,1)。

但我的名单仍然是“错误的”方式。 我错过了什么吗? 我没有任何线索。

你的比较者看起来不对我。 你仍然只是在默认的文本sorting中sorting。 当然,你想要parsing这两个数字,并根据这个sorting:

 public int Compare(Object stringA, Object stringB) { string[] valueA = stringA.ToString().Split('/'); string[] valueB = stringB.ToString().Split('/'); if (valueA.Length != 2 || valueB.Length != 2) { stringA.ToString().CompareTo(stringB.ToString())); } // Note: do error checking and consider i18n issues too :) if (valueA[0] == valueB[0]) { return int.Parse(valueA[1]).CompareTo(int.Parse(valueB[1])); } else { return int.Parse(valueA[0]).CompareTo(int.Parse(valueB[0])); } } 

(请注意,这并不适合你的问题,说明你已经通过debugging,并validation了比较是返回正确的值 – 但我恐怕我怀疑在这方面的人为错误。)

此外,斯文的权利 – 改变items的价值根本不会改变你的约束列表。 你应该添加:

 this.Items = items; 

在你的方法的底部。

我遇到了一般自然sorting的问题,并在这里写下了解决scheme:

自然sorting与Linq OrderBy()比较

您可以使用Alphanumalgorithm:

  (...) items.OrderBy(x => property.GetValue(x), new AlphanumComparator()) (...) 

哪里

AlphanumComparator是http://www.davekoelle.com/files/AlphanumComparator.cs

sorting列表只绑定到本地variables项目,而不绑定到绑定列表的Items属性,因此它仍然未sorting。

[编辑]基本上,你只是扔掉你的sorting努力的结果;-)

我们不能这样做:

 public class MyComparer : IComparer<string> { public int Compare(string stringA, string stringB) { string small = stringA; string big = stringB; if (stringA.Length > stringB.Length) { small = stringB; big = stringA; } else if (stringA.Length < stringB.Length) { small = stringA; big = stringB; } for (int j = 0; j < small.Length; j++) { if (Convert.ToInt32(small[j]) > Convert.ToInt32(big[j])) return -1; if (Convert.ToInt32(small[j]) < Convert.ToInt32(big[j])) return 1; } //big is indeed bigger if (big.Length > small.Length) return 1; //finally they are smae return 0; } } 

用法:

 string[] inputStrings = {"_abc*&","#almnp","abc" }; //string[] inputStrings = { "#", "_", "_a", "@", "_" }; MyComparer computer = new MyComparer(); var kola = inputStrings.OrderBy(x => x, new MyComparer()).ToArray(); 

这与以下相同:

  Array.Sort(inputStrings, StringComparer.Ordinal);