为什么不承认平等会把C#List搞得一团糟<;T>;分类
这是一个有点模糊的问题,但在花了一个小时追踪这个bug之后,我觉得值得问一下 我为为什么不承认平等会把C#List搞得一团糟<;T>;分类,c#,list,C#,List,这是一个有点模糊的问题,但在花了一个小时追踪这个bug之后,我觉得值得问一下 我为结构编写了自定义排序,但犯了一个错误: 我的结构有一个特殊的状态,我们称之为“min” 如果结构处于最小状态,则它比任何其他结构都小 我的CompareTo方法犯了一个错误:a.CompareTo(b)将在a为“min”时返回-1,但当然,如果b也为“min”,则应返回0 现在,这个错误彻底打乱了列表排序()方法:整个列表(有时)会以随机顺序出现 我的列表只包含一个处于“min”状态的对象 似乎我的错误只会影
结构
编写了自定义排序,但犯了一个错误:
- 我的结构有一个特殊的状态,我们称之为“min”
- 如果结构处于最小状态,则它比任何其他结构都小
- 我的
方法犯了一个错误:CompareTo
将在a.CompareTo(b)
为“min”时返回a
,但当然,如果-1
也为“min”,则应返回0b
列表排序()方法:整个列表(有时)会以随机顺序出现
- 我的列表只包含一个处于“min”状态的对象
- 似乎我的错误只会影响一个“min”对象与它自身的比较
- 为什么分拣时会发生这种情况
- 即使是这样,它怎么会导致两个“非最小”对象的相对顺序错误呢
使用LINQOrderBy
方法可能会导致无限循环
小型、完整的测试示例:
struct MyStruct:i可比较
{
公共国家;
公共MyStruct(ints){State=s;}
公共内部比较(MyStruct rhs)
{
//10为“最小”状态。否则按常规顺序订购
如果(State==10){return-1;}//不正确
/*if(State==10)//正确的版本
{
如果(rhs.State==10){返回0;}
返回-1;
}*/
如果(rhs.State==10){返回1;}
返回此.State-rhs.State;
}
公共重写字符串ToString()
{
返回String.Format(“MyStruct({0})”,State);
}
}
班级计划
{
静态int Main()
{
var list=新列表();
var rnd=新随机数();
对于(int i=0;i<20;++i)
{
int x=下一个rnd(15);
如果(x>=10){++x;}
添加(新MyStruct(x));
}
添加(新MyStruct(10));
list.Sort();
//永远不会回来。。。
//list=list.OrderBy(item=>item.ToList();
Console.WriteLine(“列表:”);
foreach(列表中的varx){Console.WriteLine(x);}
对于(int i=1;i
似乎我的错误只会影响一个“min”对象与它自身的比较
不完全是。如果有两个不同的“min”对象,也可能导致。对于在这个特定时间排序的列表,只有将该项与自身进行比较时,才会发生这种情况。但是另一种情况是值得考虑的,因为为什么向需要传递性比较器的方法提供非传递性比较器是一件非常糟糕的事情
为什么分拣时会发生这种情况
为什么不呢
List.Sort()<代码>数组。排序< /COD>反过来使用插入排序、Heapsort和QuasRoad的混合,但为了简化,让我们考虑一个通用快速排序。为了简单起见,我们将直接使用IComparable
,而不是通过System.Collections.Generic.Comparer.Default
:
public static void Quicksort<T>(IList<T> list) where T : IComparable<T>
{
Quicksort<T>(list, 0, list.Count - 1);
}
public static void Quicksort<T>(IList<T> list, int left, int right) where T : IComparable<T>
{
int i = left;
int j = right;
T pivot = list[(left + right) / 2];
while(i <= j)
{
while(list[i].CompareTo(pivot) < 0)
i++;
while(list[j].CompareTo(pivot) > 0)
j--;
if(i <= j)
{
T tmp = list[i];
list[i] = list[j];
list[j] = tmp;
i++;
j--;
}
}
if(left < j)
Quicksort(list, left, j);
if(i < right)
Quicksort(list, i, right);
}
publicstaticvoidquicksort(IList列表),其中T:IComparable
{
快速排序(列表,0,列表.计数-1);
}
公共静态void快速排序(IList列表,int left,int right),其中T:IComparable
{
int i=左;
int j=右;
T轴=列表[(左+右)/2];
而(i 0)
j--;
如果(我不考虑实现),考虑一些重复一组项目的例程,寻找一个小于或等于该集合中特定已知成员的例程。代码在到达终点时不必做任何特殊的事情,因为它“知道”。至少它会遇到实际的成员。直到它遇到你的坏的相等函数。哦,并且在一个有效的数字范围中间使用一个神奇的数字,这让我很痒。这是一个实现细节。在处理传递性比较结果的知识的过程中建立了许多排序例程,这意味着如果A<B。b