原文:http://topic.csdn.net/u/20090407/13/371533da-f709-4f1f-bda9-b4a18060e713.html?seed=924471686
有时候我们需要对集合中的自定义对象进行排序,以最原始的 System.Array 为例,如
-
Person[] people = new Person[]{
new Person( 3 , " Andy " , new DateTime( 1982 , 10 , 3 )),
new Person( 1 , " Tom " , new DateTime( 1993 , 2 , 10 )),
new Person( 2 , " Jerry " , new DateTime( 1988 , 4 , 23 ))
};
-
class Person
{
public int Id { get ; set ; }
public string Name { get ; set ; }
public DateTime Birthday { get ; set ; }
public Person( int id, string name, DateTime birthday)
{
Id = id;
Name = name;
Birthday = birthday;
}
public override string ToString()
{
return String.Format( " Id: {0,-6}Name: {1,-20}Birthday: {2:yyyy-MM-dd} " , Id, Name, Birthday);
}
}
-
public static void Sort < T > (
T[] array,
Comparison < T > comparison
)
-
static int CompareById(Person first, Person second)
{
if (first.Id > second.Id)
return 1 ;
if (first.Id == second.Id)
return 0 ;
return - 1 ;
}
-
Array.Sort(people, new Comparison < Person > (CompareById));
-
foreach (Person p in people)
Console.WriteLine(p);
-
static int CompareById(Person first, Person second)
{
return first.Id.CompareTo(second.Id);
}
-
Array.Sort(people, delegate (Person first, Person second){
return first.Id.CompareTo(second.Id);
});
-
Array.Sort(people, (first, second) => first.Id.CompareTo(second.Id));
能否直接返回一个委托,使我们不必关心 Person 类的具体属性比较,而直接根据属性进行排序呢?答案是肯定的。为 Person 类添加一个静态方法:
-
public static Comparison < Person > CompareByProperty( string name)
{
switch (name)
{
case " Id " :
return (first, second) => first.Id.CompareTo(second.Id);
case " Name " :
return (first, second) => first.Name.CompareTo(second.Name);
case " Birthday " :
return (first, second) => first.Birthday.CompareTo(second.Birthday);
default :
throw new Exception( " 属性 " + name + " 不存在。 " );
}
}
-
Array.Sort(people, Person.CompareByProperty( " Birthday " ));
-
public static Comparison < Person > CompareByProperty( string name)
{
Type typeOfPerson = typeof (Person);
PropertyInfo p = typeOfPerson.GetProperty(name);
if (p == null )
throw new Exception( " 属性 " + name + " 不存在。 " );
// 假定该类所有的属性均实现了接口 IComparable
return (first, second) => ((IComparable)p.GetValue(first, null )).CompareTo(p.GetValue(second, null ));
}
仔细观察上面的代码,应该可以把它的应用再扩大化,而不仅限于 Person 类,而这显然是泛型的长项。当然,这样的话,不应再把这个方法放在 Person 类中,我们暂时先把它移到主程序中,稍后再为它寻找一个好的归宿,修改后的CompareByProperty 泛型方法代码如下:
-
public static Comparison < T > CompareByProperty < T > ( string name)
{
Type typeOfPerson = typeof (T);
PropertyInfo p = typeOfPerson.GetProperty(name);
if (p == null )
throw new Exception( " 属性 " + name + " 不存在。 " );
// 假定该类所有的属性均实现了接口 IComparable
return (first, second) => ((IComparable)p.GetValue(first, null )).CompareTo(p.GetValue(second, null ));
}
-
Array.Sort(people, CompareByProperty < Person > ( " Name " ));
-
static class ExtensionArray
{
public static void SortBy( this Array array, string name)
{
Type elementType = array.GetType().GetElementType();
Type bridge = typeof (Bridge <> ).MakeGenericType(elementType);
MethodInfo sortMethod = bridge.GetMethod( " Sort " );
sortMethod.Invoke( null , new object [] { array, name });
}
private static class Bridge < T >
{
private static Comparison < T > CompareByProperty( string name) // 不必再是泛型方法
{
Type typeOfPerson = typeof (T);
PropertyInfo p = typeOfPerson.GetProperty(name);
if (p == null )
throw new Exception( " 属性 " + name + " 不存在。 " );
// 假定该类所有的属性均实现了接口 IComparable
return (first, second) => ((IComparable)p.GetValue(first, null )).CompareTo(p.GetValue(second, null ));
}
public static void Sort(Array array, string name)
{
Array.Sort((T[])array, CompareByProperty(name));
}
}
}
现在按属性排序只需这样调用:
-
people.SortBy( " Birthday " );