Code Bye

一个自定义排序器,为什么无限循环执行?

 
{
    static void Main(string[] args)
    {
        DataTable tbl = new DataTable("Customers");
        tbl.Columns.Add("PersonName", typeof(string));
        tbl.Columns.Add("PersonAge", typeof(Int32));
        DataRow row = tbl.NewRow();
        row["PersonName"] = "张三";
        row["PersonAge"] = "22";
        tbl.Rows.Add(row);
        row = tbl.NewRow();
        row["PersonName"] = "李四";
        row["PersonAge"] = "25";
        tbl.Rows.Add(row);
        List<DataRow> ListRows = new List<DataRow>();
        foreach (DataRow r in tbl.Rows)
        {
            ListRows.Add(r);
        }
        Func<DataRow, DataRow> MyFunc = new Func<DataRow, DataRow>((Row) =>
        {
            return Row;
        });
        ListRows = Enumerable.OrderBy(ListRows, MyFunc, new PersonComparer()).ToList();
        Console.WriteLine(ListRows.Count());
        Console.ReadKey();
    }
}
public class PersonComparer : IComparer<DataRow>
{
    public int Compare(DataRow x, DataRow y)
    {
       return 1;
    }
}

在上面的代码中,有一个List<DataRow>类型的对象,有一个自定义的排序器,使用这个排序器对ListRows排序。
结果是,无法输出ListRows.Count(),通过设置断点,发现代码在无限循环执行PersonComparer 方法,请问,这是什么故障?
如果取消ToList()方法,写成:var c = Enumerable.OrderBy(ListRows, MyFunc, new PersonComparer());这种,就不会无限循环执行PersonComparer 方法,
这是何故呢?

没人知道吗?
3分
ToList()之后才会无线循环???
ToList了可以直接list.Count了啊,干嘛还要扩展方法
引用 2 楼 starfd 的回复:

ToList()之后才会无线循环???
ToList了可以直接list.Count了啊,干嘛还要扩展方法

不知道为什么会无限循环执行..

43分
引用 楼主 fder45f 的回复:
public class PersonComparer : IComparer<DataRow>
{
    public int Compare(DataRow x, DataRow y)
    {
       return 1;
    }
}


如果取消ToList()方法,写成:var c = Enumerable.OrderBy(ListRows, MyFunc, new PersonComparer());这种,就不会无限循环执行PersonComparer 方法,
这是何故呢?

因为你PersonComparer实现有错误,它一会儿说A>B,一会儿说B>A,一会儿说A>A。结果就是排序的算法被迷惑了,不断的调整位置,没完没了。

如果‘取消ToList()方法’,那么var c = …本身只是给出一个表达式(还没有真正开始排序),因此还看不到死循环。
而一旦展开了表达式(比如ToList),排序就会真正运行。

要解决问题很简单,正确实现‘比较’就可以了:

public class PersonComparer : IComparer<DataRow>
{
    public int Compare(DataRow x, DataRow y)
    {
        return (int)x["PersonAge"] - (int)y["PersonAge"];
    }
}
2分
LZ说他ToList没死循环,是list.Count()出现死循环……
如果没ToList,直接调用Count()楼主又说不会死循环,等其它人来解惑

当然目前来说自己还没做个测试验证,也许该实际做过验证……

引用 4 楼 Forty2 的回复:
Quote: 引用 楼主 fder45f 的回复:
public class PersonComparer : IComparer<DataRow>
{
    public int Compare(DataRow x, DataRow y)
    {
       return 1;
    }
}


如果取消ToList()方法,写成:var c = Enumerable.OrderBy(ListRows, MyFunc, new PersonComparer());这种,就不会无限循环执行PersonComparer 方法,
这是何故呢?

因为你PersonComparer实现有错误,它一会儿说A>B,一会儿说B>A,一会儿说A>A。结果就是排序的算法被迷惑了,不断的调整位置,没完没了。

如果‘取消ToList()方法’,那么var c = …本身只是给出一个表达式(还没有真正开始排序),因此还看不到死循环。
而一旦展开了表达式(比如ToList),排序就会真正运行。

要解决问题很简单,正确实现‘比较’就可以了:

public class PersonComparer : IComparer<DataRow>
{
    public int Compare(DataRow x, DataRow y)
    {
        return (int)x["PersonAge"] - (int)y["PersonAge"];
    }
}
引用 4 楼 Forty2 的回复:

它一会儿说A>B,一会儿说B>A,一会儿说A>A。结果就是排序的算法被迷惑了,不断的调整位置,没完没了。

我直接return 1,有什么错啊,你说的”一会儿说A>B,一会儿说B>A,一会儿说A>A “从何说起啊?

42分
引用 6 楼 fder45f 的回复:

我直接return 1,有什么错啊,你说的”一会儿说A>B,一会儿说B>A,一会儿说A>A “从何说起啊?

    public int Compare(DataRow x, DataRow y)
    {
       return 1;
    }
这里返回1,表示x比y大。

想象这种比较:

PersonComparer comparer = new PersonComparer();
DataRow A = ListRows[0];
DataRow B = ListRows[1];
int d1 = comparer.Compare(A, B);   // 返回1,A>B
int d2 = comparer.Compare(B, A);   // 返回1,B>A
int d3 = comparer.Compare(A, A);   // 返回1,A>A
引用 7 楼 Forty2 的回复:

想象这种比较:

PersonComparer comparer = new PersonComparer();
DataRow A = ListRows[0];
DataRow B = ListRows[1];
int d1 = comparer.Compare(A, B);   // 返回1,A>B
int d2 = comparer.Compare(B, A);   // 返回1,B>A
int d3 = comparer.Compare(A, A);   // 返回1,A>A

你的意思是,像这种交换A、B位置,不能明确比较出大小的,就会造成无线循环,是吗?
如果是的话,诸如
if (x == null && y == null)
       return -1;
这种语句,如果A、B都是null的话,也会造成无限循环吧

10分
 public int Compare(DataRow x, DataRow y)
    {
       return 1;
    }

你这个都没得比较当然无限了。你总得有个比较才行


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明一个自定义排序器,为什么无限循环执行?