我在创建自己的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);
我做错了什么?请指教。谢谢。
答案 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();
}
}