实现ICompare接口的通用对象比较类
当我们使用Array及ArrayList的Sort方法或BinarySearch方法时,通常需要提供一个实现ICompare接口的类。虽然实现ICompare接口并不复杂但是重复这些写法基本相同的代码,让人感觉到索然无味,那有没有一种通用的方法一劳永逸呢?对于这个问题dannyr兄分享了他的方法《任意对象数组ArrayList的排序法(可自定义排序字段、排序方向) 》。但是dannyr兄的方法有几个小问题:
/// <summary>
/// 通用对象比较类,一般用于对一个对象数组按属性排序或查询
/// </summary>
public class ObjectCompare : System.Collections.IComparer
{
SortEntry[] _sortEntrys;
/// <summary>
/// 构造函数,制定排序方法
/// </summary>
/// <param name="type">对象的类型</param>
/// <param name="args">排序方法</param>
public ObjectCompare(Type type, params SortEntry[] args)
{
_sortEntrys = args;
//为防止因为指定的排序字段的值一样而造成每次的排序结果不同,再加属性和字段做为辅助
int j = args.Length;
PropertyInfo[] pis = type.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
FieldInfo[] fis = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
_sortEntrys = new SortEntry[_sortEntrys.Length + pis.Length + fis.Length];
args.CopyTo(_sortEntrys, 0);
foreach (PropertyInfo pi in pis)
_sortEntrys[j++] = new SortEntry(pi.Name, pi.PropertyType, false);
foreach (FieldInfo fi in fis)
_sortEntrys[j++] = new SortEntry(fi.Name, fi.FieldType, false);
}
IComparer Members
public object GetObjectPropertyValue(object obj, string propertyName)
}
/// <summary>
/// 排序方式设定
/// </summary>
public struct SortEntry
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="propertyName">属性名</param>
/// <param name="value">是否倒序</param>
public SortEntry(string propertyName) : this(propertyName, typeof(string), false) { }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="propertyName">属性名</param>
/// <param name="value">是否倒序</param>
public SortEntry(string propertyName, bool isDescend) : this(propertyName, typeof(string), isDescend) { }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="propertyName">属性名</param>
/// <param name="value">是否倒序</param>
/// <param name="type">属性类型</param>
public SortEntry(string propertyName, Type type, bool isDescend)
{
if (propertyName + "" == "")
throw new Exception("属性名不能为空!");
if (type == null)
throw new Exception("属性的类型不能为空!");
_propertyName = propertyName;
_descend = isDescend;
_type = type;
}
/// <summary>
/// 属性名
/// </summary>
string _propertyName;
public string PropertyName { get { return _propertyName; } set { _propertyName = value; } }
/// <summary>
/// 是否倒序
/// </summary>
bool _descend;
public bool Descend { get { return _descend; } set { _descend = value; } }
Type _type;
/// <summary>
/// 属性的类型
/// </summary>
/// <value></value>
public Type ProeprtyType { get { return _type; } set { _type = value; } }
}
测试代码:
struct Test
{
public Test(string a, int b, string c)
{
A = a;
B = b;
C = c;
}
public string A;
public int B;
public string C;
}
class Program
{
static void Main(string[] args)
{
ArrayList al = new ArrayList();
for (int i = 0; i < 10; i++)
{
al.Add(new Test("A" + i, 1, "1"));
al.Add(new Test("C" + i, 2, "2"));
al.Add(new Test("B" + i, 1, "3"));
al.Add(new Test("A" + i, 3, "4"));
al.Add(new Test("D" + i, 2, "5"));
![]()
}
![]()
Console.WriteLine("默认排序1");
al.Sort(new ObjectCompare(typeof(Test),new SortEntry("A")));
Output(al);
Console.WriteLine("默认排序2");
al.Sort(new ObjectCompare(typeof(Test)));
Output(al);
![]()
Console.WriteLine("按属性A排序1");
al.Sort(new ObjectCompare(typeof(Test),new SortEntry("A")));
Output(al);
![]()
Console.WriteLine("按属性A排序2");
al.Sort(new ObjectCompare(typeof(Test),new SortEntry("A")));
Output(al);
![]()
Console.WriteLine("按属性B排到序1");
al.Sort(new ObjectCompare(typeof(Test),new SortEntry("B", typeof(int), true)));
Output(al);
![]()
Console.WriteLine("按属性B排到序2");
al.Sort(new ObjectCompare(typeof(Test),new SortEntry("B", typeof(int), true)));
Output(al);
![]()
Console.ReadLine();
}
![]()
static void Output(ArrayList al)
{
foreach (Test obj in al)
{
Console.WriteLine("A:{0}\tB:{1}\tC:{2}", obj.A, obj.B, obj.C);
}
Console.WriteLine("------");
Console.Write("\r\n\r\n\r\n");
}
}
- 不能按多个属性或字段排序。
- 如果指定两个对象的属性的值一样(不是两个对象一样),则按这个属性排序后,每排一次对象的位置就变化一下,不稳定。这会对应用到实际的项目中造成困扰。
- 不能指定属性排序时的类型(只能按字符串比较),如作为int来比较。
因此又把自己以前写的代码整理了一下(从实际项目的代码中RIP出来的),帖出来和大家分享。
实现类代码:
测试代码:
struct Test
{
public Test(string a, int b, string c)
{
A = a;
B = b;
C = c;
}
public string A;
public int B;
public string C;
}
class Program
{
static void Main(string[] args)
{
ArrayList al = new ArrayList();
for (int i = 0; i < 10; i++)
{
al.Add(new Test("A" + i, 1, "1"));
al.Add(new Test("C" + i, 2, "2"));
al.Add(new Test("B" + i, 1, "3"));
al.Add(new Test("A" + i, 3, "4"));
al.Add(new Test("D" + i, 2, "5"));
}
Console.WriteLine("默认排序1");
al.Sort(new ObjectCompare(typeof(Test),new SortEntry("A")));
Output(al);
Console.WriteLine("默认排序2");
al.Sort(new ObjectCompare(typeof(Test)));
Output(al);
Console.WriteLine("按属性A排序1");
al.Sort(new ObjectCompare(typeof(Test),new SortEntry("A")));
Output(al);
Console.WriteLine("按属性A排序2");
al.Sort(new ObjectCompare(typeof(Test),new SortEntry("A")));
Output(al);
Console.WriteLine("按属性B排到序1");
al.Sort(new ObjectCompare(typeof(Test),new SortEntry("B", typeof(int), true)));
Output(al);
Console.WriteLine("按属性B排到序2");
al.Sort(new ObjectCompare(typeof(Test),new SortEntry("B", typeof(int), true)));
Output(al);
Console.ReadLine();
}
static void Output(ArrayList al)
{
foreach (Test obj in al)
{
Console.WriteLine("A:{0}\tB:{1}\tC:{2}", obj.A, obj.B, obj.C);
}
Console.WriteLine("------");
Console.Write("\r\n\r\n\r\n");
}
}

浙公网安备 33010602011771号