IComparer多属性比较问题:List.Sort()抛出不一致结果异常
问题排查与修复
你的自定义IComparer<UserModel>抛出异常的核心原因是:处理字符串null值时违反了比较器的对称性规则(即Compare(a,b)必须等于-Compare(b,a)),同时破坏了自反性(Compare(a,a)需返回0)。
具体错误场景
当两个UserModel实例的Surname都为null时:
- 调用
Compare(l, r)会触发if (l.Surname == null) return -1;,返回-1 - 调用
Compare(r, l)同样会触发if (r.Surname == null) return -1;,也返回-1
这种矛盾的比较结果会让排序算法认为l < r且r < l,直接导致异常。
修复后的代码
利用string.Compare原生支持null值比较的特性(已遵循正确的排序逻辑:null排在非null字符串前,同null视为相等),可以简化代码并彻底解决问题:
class CustomComparer : IComparer<UserModel> { public int Compare(UserModel l, UserModel r) { // 处理UserModel实例为null的情况 if (l == null && r == null) return 0; if (l == null) return -1; if (r == null) return 1; // 直接用string.Compare处理Surname的null比较 int surnameCompare = string.Compare(l.Surname, r.Surname); if (surnameCompare != 0) return surnameCompare; // 同理处理GivenName的null比较 return string.Compare(l.GivenName, r.GivenName); } }
修复逻辑说明
string.Compare的null处理完全符合你的需求:
string.Compare(null, null)返回0(两个null字段视为相等)string.Compare(null, "Smith")返回-1(null字段排在前面)string.Compare("Smith", null)返回1(非null字段排在后面)
这样实现的比较器严格遵守IComparer的所有规则,既能完成先按Surname再按GivenName的排序,也能支持后续的BinarySearch()操作。
内容的提问来源于stack exchange,提问作者oflahero
相关产品推荐
相关产品推荐

