通用的泛型Icomparer生成类,对类进行排序,最大支持4个字段同时比较

来源:互联网 发布:淘宝上汽车配件 编辑:程序博客网 时间:2024/06/04 17:59

一,通常我们自己定义一个类,然后对类的集合进行排序,是下面这样的做法

        class People        {            public int ID { get; set; }            public string Name { get; set; }            public DateTime Birthday { get; set; }            public override string ToString()            {                return string.Format("{0},{1},{2}", ID, Name, Birthday);            }        }


再定义一个类继承IComparer<People>接口

        /// <summary>        /// user define        /// </summary>        class PeopleCompare : IComparer<People>        {            #region IComparer<People>             public int Compare(People x, People y)            {                return Comparer<int>.Default.Compare(x.ID, y.ID);            }            #endregion        }


调用代码:

        public static void TestFunc()        {            var peoples = new People[] {             new People{ID = 1,Name = "a123",Birthday = new DateTime(2000,05,01)},            new People{ID = 4,Name = "b123",Birthday = new DateTime(2000,04,01)},            new People{ID = 2,Name = "d123",Birthday = new DateTime(2000,02,01)},            new People{ID = 3,Name = "e123",Birthday = new DateTime(2000,04,01)},            };            Array.Sort(peoples, new PeopleCompare());                        peoples.ForEach<People>(p => System.Diagnostics.Debug.WriteLine(p));        }


结果输出如下:

1,a123,2000/05/01 0:00:002,d123,2000/02/01 0:00:003,e123,2000/04/01 0:00:004,b123,2000/04/01 0:00:00


,如果我们又定义了Cat,Monkey等等这样的类,就得每次都写一个类似于PeopleCompare的类,当然你也可以在定义People的时候继承Icomparable接口,本文不讨论。

这样做有大量的重复工作,现在考虑定义一个泛型的方法来创建通用的继承了IComparer的类,并且考虑到类有多个字段,对多个字段的排序也考虑进去。下面的这个类定义了一个最大支持4个字段的ComparerFactory类,一般应用已经足够了。

        /// <summary>        /// Common Comaparer Generate Class, supported 4 paramers limitted        /// </summary>        /// <typeparam name="T"></typeparam>        public static class ComparerFactroy<T>        {            public static IComparer<T> Create<V1>(Func<T, V1> keySelector1)            {                return new MyCommonComparer<V1, Object, Object, Object>(keySelector1,Comparer<V1>.Default,null,null,null, null, null, null);            }            public static IComparer<T> Create<V1, V2>(Func<T, V1> keySelector1, Func<T, V2> keySelector2)            {                return new MyCommonComparer<V1, V2, Object, Object>(keySelector1,Comparer<V1>.Default, keySelector2,Comparer<V2>.Default,null,null, null, null);            }            public static IComparer<T> Create<V1, V2, V3>(Func<T, V1> keySelector1, Func<T, V2> keySelector2, Func<T, V3> keySelector3)            {                return new MyCommonComparer<V1, V2, V3, Object>(keySelector1, Comparer<V1>.Default, keySelector2, Comparer<V2>.Default, keySelector3, Comparer<V3>.Default, null,null);            }            public static IComparer<T> Create<V1, V2, V3,V4>(Func<T, V1> keySelector1, Func<T, V2> keySelector2, Func<T, V3> keySelector3, Func<T, V4> keySelector4)            {                return new MyCommonComparer<V1, V2, V3, V4>(keySelector1, Comparer<V1>.Default, keySelector2, Comparer<V2>.Default, keySelector3, Comparer<V3>.Default, keySelector4,Comparer<V4>.Default);            }            class MyCommonComparer<V1,V2,V3,V4> : IComparer<T>            {                Func<T, V1> keySelector1;                Func<T, V2> keySelector2;                Func<T, V3> keySelector3;                Func<T, V4> keySelector4;                IComparer<V1> comparer1;                IComparer<V2> comparer2;                IComparer<V3> comparer3;                IComparer<V4> comparer4;                public MyCommonComparer(Func<T, V1> keySelector1, IComparer<V1> compare1,                                        Func<T, V2> keySelector2, IComparer<V2> compare2,                                        Func<T, V3> keySelector3, IComparer<V3> compare3,                                        Func<T, V4> keySelector4, IComparer<V4> compare4)                {                    this.keySelector1 = keySelector1;                    this.keySelector2 = keySelector2;                    this.keySelector3 = keySelector3;                    this.keySelector4 = keySelector4;                    this.comparer1 = compare1;                    this.comparer2 = compare2;                    this.comparer3 = compare3;                    this.comparer4 = compare4;                }                #region IComparer<T> メンバ                public int Compare(T x, T y)                {                    int retVal = 0;                    if (keySelector1 != null)                        retVal = comparer1.Compare(keySelector1(x), keySelector1(y));                    if (keySelector2 != null && retVal == 0)                        retVal = comparer2.Compare(keySelector2(x), keySelector2(y));                    if (keySelector3 != null && retVal == 0)                        retVal = comparer3.Compare(keySelector3(x), keySelector3(y));                    if (keySelector4 != null && retVal == 0)                        retVal = comparer4.Compare(keySelector4(x), keySelector4(y));                    return retVal;                }                #endregion            }        }


ComparerFactory的Create方法根据你传的类型,创建一个Comparer,Create方法有4个重载,可以对1,2,3,4个字段进行排序。

继续用上面定义的People类测试,使用方法如下:

        public static void TestFunc()        {            var peoples = new People[] {                 new People{ID = 1,Name = "a123",Birthday = new DateTime(2000,05,01)},                new People{ID = 4,Name = "b123",Birthday = new DateTime(2000,04,01)},                new People{ID = 2,Name = "d123",Birthday = new DateTime(2000,02,01)},                new People{ID = 3,Name = "e123",Birthday = new DateTime(2000,04,01)},                new People{ID = 3,Name = "e123",Birthday = new DateTime(2000,03,01)},                new People{ID = 3,Name = "c123",Birthday = new DateTime(2000,03,01)}                };            Array.Sort(peoples, ComparerFactroy<People>.Create(p => p.ID, p => p.Name, p => p.Birthday));            peoples.ForEach<People>(p => System.Diagnostics.Debug.WriteLine(p));        }


分别根据People的ID,Name,Birthday进行排序

测试结果:

1,a123,2000/05/01 0:00:002,d123,2000/02/01 0:00:003,c123,2000/03/01 0:00:003,e123,2000/03/01 0:00:003,e123,2000/04/01 0:00:004,b123,2000/04/01 0:00:00


可以继续完善的地方:

1,现在默认是每个字段的升序排列,可以在参数中每个字段的升序降序排列。

2,现在只支持4个字段,扩充字段代码改动较大,不知道还有没有更好的支持多字段的写法,欢迎一起讨论。

原创粉丝点击