IComparer <t>实现排序List <t>的麻烦

时间:2017-04-09 10:23:14

标签: c#

我在创建自己的List结构时遇到了一些麻烦。我正在尝试创建一个名为SortedList的List结构。目标是在添加新项目后立即对其项目进行排序。这个列表在我正在使用它的项目中不会太大(最多可能是50-100项)。但是,我通过添加一个具有Name属性的Employee类的简单项来进行测试。我希望这个SortedList对员工的姓名进行排序。

这是我的尝试。

员工类

public class Employee : IComparer<Employee>
{
    public string Name { get; set; }

    public Employee()
    {
    }

    public int Compare(Employee x, Employee y)
    {
        return string.Compare(x.Name, y.Name,true);
    }

}

这是我正在尝试创建的SortedList类。

public class SortedList<T> : IEnumerable<T>
{
    private List<T> _list;

    public List<T> List
    {
        get { return _list; }
        set { _list = value; }
    }

    private Employee EmployeeComparer = new Employee();

    public SortedList()
    {
        _list = new List<T>();
    }


    public void Insert(T item)
    {
        if (!_list.Contains(item))
        {
            _list.Add(item);
            Sort(_list);
        }
    }


    private void Sort(List<T> list)
    {
        var type = typeof(T);

        switch (type.Name)
        {
            case "Int32":
            case "String":
                list.Sort();
                break;

            case "Employee":
                Employee EmployeeComparer = new Employee();
                list.Sort(EmployeeComparer);
                break;

        }
    }


    public IEnumerator<T> GetEnumerator()
    {
        return _list.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

从program.cs我基本上用三个Employee对象实例填充SortedList,我希望它按员工的Name属性对它进行排序,并且在out put中我期望看到它。

百里

尼尔

扎克

class Program
{
    static void Main(string[] args)
    {

        SortedList<Employee> list = new SortedList<Employee>();
        list.Insert(new Employee() { Name="Zach"});
        list.Insert(new Employee() { Name = "Neil" });
        list.Insert(new Employee() { Name = "Barry" });


        foreach (var item in list)
        {
            Console.WriteLine(item.Name);
        }

    }
}

但是我收到编译错误。它说:

Severity    Code    Description Project File    Line    Suppression State
Error   CS1503  Argument 1: cannot convert from 'ExtensingLists.Employee' to 'System.Collections.Generic.IComparer<T>'  ExtensingLists  C:\E Drive\VSProjects\C-Sharp Generics Course\ExtensingLists\ExtensingLists\SortedList.cs   57  Active

错误表示第57行,即:

            list.Sort(EmployeeComparer);

我做错了什么?请指教。谢谢。

2 个答案:

答案 0 :(得分:2)

您提出的具体问题就像问为什么

int f(object o) { return o is int ? o : 0; }

无法编译。即使您在运行时检查o类型为int,但在编译时它仍然具有object类型,这意味着它无法使用作为返回值。你需要一个演员来实现这个目标:

int f(object o) { return o is int ? (int)o : 0; }

同样适用于您的代码。

但是有一些根本错误的东西。您的Employee不应该实施IComparer<Employee>。它应该是实现IComparable<Employee>,它不指定Employee对象知道如何比较另外两个Employee对象,但它知道如何比较本身另一个Employee对象。当你这样做时,你应该可以只调用list.Sort();而不检查类型。

答案 1 :(得分:1)

可以使List.Sort方法以多种方式工作。

  

此方法使用类型T的默认比较器Comparer.Default来确定列表元素的顺序。 Comparer.Default属性检查类型T是否实现IComparable通用接口并使用该实现(如果可用)。如果不是,Comparer.Default检查类型T是否实现IComparable接口。如果类型T没有实现任何一个接口,Comparer.Default会抛出InvalidOperationException。

通过进行以下更改,它将开始为您工作

public class Employee : IComparable<Employee> {
    public string Name { get; set; }

    public Employee() {
    }

    public int CompareTo(Employee other) {
        return string.Compare(Name, other.Name, true);
    }
}

以及public class SortedList<T> : IEnumerable<T> {

中的以下更改
private static void Sort(List<T> list) {
    var type = typeof(T);
    list.Sort();
}

这不是唯一的方法,但是当类型本身Orderable时,这是一种更好的方法。您也可以使用IComparer<T>接口,但是当需要以IComparable<T>不匹配或类型不是IComparable<T>的方式对类型进行排序时使用。我在这里列出了所有代码

class Program {

    static void Main() {
        SortedList<Employee> list = new SortedList<Employee>();
        list.Insert(new Employee() { Name = "Zach" });
        list.Insert(new Employee() { Name = "Neil" });
        list.Insert(new Employee() { Name = "Barry" });


        foreach (var item in list) {
            Console.WriteLine(item.Name);
        }

    }
}

public class Employee : IComparable<Employee> {
    public string Name { get; set; }

    public int Age { get; set; }

    public Employee() {
    }

    public int CompareTo(Employee other) {
        return string.Compare(Name, other.Name, true);
    }
}


public class EmployeeAgeComparer : IComparer<Employee> {
    public int Compare(Employee x, Employee y) {
        return x.Age - y.Age;
    }
}

public class SortedList<T> : IEnumerable<T> {
    private List<T> _list;

    public List<T> List {
        get { return _list; }
        set { _list = value; }
    }

    private EmployeeAgeComparer EmployeeComparer = new EmployeeAgeComparer();

    public SortedList() {
        _list = new List<T>();
    }


    public void Insert(T item) {
        if (!_list.Contains(item)) {
            _list.Add(item);
            Sort(_list);
        }
    }

    private void Sort(List<T> list) {
        if (typeof(T) == typeof(Employee))
            list.Sort((IComparer<T>)EmployeeComparer);
        else
            list.Sort();
    }


    public IEnumerator<T> GetEnumerator() {
        return _list.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator() {
        return GetEnumerator();
    }
}