C# – 使用扩展方法排序

我想排序一个人说的清单

List persons=new List(); persons.Add(new Person("Jon","Bernald",45000.89)); persons.Add(new Person("Mark","Drake",346.89)); persons.Add(new Person("Bill","Watts",456.899)); 

基于

 public enum CompareOptions { ByFirstName, ByLastName, BySalary } public enum SortOrder { Ascending, Descending } 

使用lambda表达式排序的方法是什么?

  public static List SortPeople(this List lst, CompareOptions opt1,SortOrder ord) { lst.Sort((p,op1,op2)=>{ how to apply lambda expression here}); } 

看起来你试图在List上调用Sort方法,它接受一个Comparison委托。 这需要一些工作,因为您首先必须定义兼容的比较function。

第一步是根据CompareOptions值编写比较函数

 private static Comparison Create(CompareOptions opt) { switch (opt) { case CompareOptions.ByFirstName: (x,y) => x.FirstName.CompareTo(y.FirstName); case CompareOptions.ByLastName: (x,y) => x.LastName.CompareTo(y.LastName); case CompareOptions.BySalary: (x,y) => x.Salary - y.Salary; default: throw new Exception(); } } 

默认情况下,此function将按升序排序。 如果你想让它下降只是否定价值。 所以现在编写SortPeople可以通过以下方式完成

 public static List SortPeople( this List list, CompareOptions opt1, SortOrder ord) ) var original = Create(opt1); var comp = original; if( ord == SortOrder.Descending ) { comp = (x,y) => -(orig(x,y)); } list.Sort(comp); } 

编辑

在lambda中100%完成的版本

 public static List SortPeople( this List list, CompareOptions opt1, SortOrder ord) ) list.Sort( (x,y) => { int comp = 0; switch (opt) { case CompareOptions.ByFirstName: comp = x.FirstName.CompareTo(y.FirstName); case CompareOptions.ByLastName: comp = x.LastName.CompareTo(y.LastName); case CompareOptions.BySalary: comp = x.Salary.CompareTo(y.Salary); default: throw new Exception(); } if ( ord == SortOrder.Descending ) { comp = -comp; } return comp; }); } 

你真的需要枚举吗? 我不认为在一个方法中封装你的搜索逻辑比使用linq方法更清晰或更干燥:

 persons.OrderBy( p => p.FirstName ); persons.OrderByDescending( p => p.Salary); 

等等

为了使其在lambda中工作,表达式需要形成Comparison签名。 这将需要2个“人”实例。 你可以这样做:

 public static void SortPeople( this List lst, CompareOptions opt1,SortOrder ord) { lst.Sort((left, right) => { int result; // left and right are the two Person instances if (opt1 == CompareOptions.Salary) { result = left.Salary.CompareTo(right.Salary); } else { string compStr1, compStr2; if (opt1 == CompareOptions.FirstName) { compStr1 = left.FirstName; compStr2 = right.FirstName; } else { compStr1 = left.LastName; compStr2 = right.LastName; } result = compStr1.CompareTo(compStr2); } if (ord == SortOrder.Descending) result *= -1; return result; }); } 
 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { List persons = new List(); persons.Add(new Person("Jon", "Bernald", 45000.89)); persons.Add(new Person("Mark", "Drake", 346.89)); persons.Add(new Person("Bill", "Watts", 456.899)); persons.SortPeople(CompareOptions.ByFirstName, SortOrder.Ascending); persons.ForEach(p => Console.WriteLine(p.ToString())); persons.SortPeople(CompareOptions.ByFirstName, SortOrder.Descending); persons.ForEach(p => Console.WriteLine(p.ToString())); persons.SortPeople(CompareOptions.ByLastName, SortOrder.Ascending); persons.ForEach(p => Console.WriteLine(p.ToString())); persons.SortPeople(CompareOptions.ByLastName, SortOrder.Descending); persons.ForEach(p => Console.WriteLine(p.ToString())); persons.SortPeople(CompareOptions.BySalary, SortOrder.Ascending); persons.ForEach(p => Console.WriteLine(p.ToString())); persons.SortPeople(CompareOptions.BySalary, SortOrder.Descending); persons.ForEach(p => Console.WriteLine(p.ToString())); Console.ReadLine(); } } public static class Extensions { public static void SortPeople(this List lst, CompareOptions opt1,SortOrder ord){ lst.Sort((Person p1, Person p2) => { switch (opt1) { case CompareOptions.ByFirstName: return ord == SortOrder.Ascending ? p1.FirstName.CompareTo(p2.FirstName) : p2.FirstName.CompareTo(p1.FirstName); case CompareOptions.ByLastName: return ord == SortOrder.Ascending ? p1.LastName.CompareTo(p2.LastName) : p2.LastName.CompareTo(p1.LastName); case CompareOptions.BySalary: return ord == SortOrder.Ascending ? p1.Salary.CompareTo(p2.Salary) : p2.Salary.CompareTo(p1.Salary); default: return 0; } }); } } public class Person { public double Salary { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public Person(string first, string last, double salary) { this.Salary = salary; this.FirstName = first; this.LastName = last; } public override string ToString() { return string.Format("{0} {1} has a salary of {2}", this.FirstName, this.LastName, this.Salary); } } public enum CompareOptions { ByFirstName, ByLastName, BySalary } public enum SortOrder { Ascending, Descending } 

}