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

一个自定义排序器,为什么无限循环执行?
本帖最后由 fder45f 于 2015-04-20 19:01:31 编辑

{
    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 方法,
这是何故呢?
------解决思路----------------------
ToList()之后才会无线循环???
ToList了可以直接list.Count了啊,干嘛还要扩展方法
------解决思路----------------------
引用:

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"];
    }
}

------解决思路----------------------
LZ说他ToList没死循环,是list.Count()出现死循环……
如果没ToList,直接调用Count()楼主又说不会死循环,等其它人来解惑

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

引用:
Quote: 引用:


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"];
    }
}

------解决思路----------------------
引用:
我直接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



------解决思路----------------------
 public int Compare(DataRow x, DataRow y)
    {
       return 1;
    }

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