星期天 十一月 29, 2009 13:01

cSharp数组的学习笔记

Posted by 邵 明博

这一章主要是2对接口的辨析让人纠结。不过,我们还是一对一对的来看,首先将要出场的是IEnumerable Vs IEnumerator.

IEnumerable 接口中需要实现一个GetEnumerator()方法,它返回一个IEnumerator 接口。在IEnumerator 中有MoveNext()  方法Reset() 方法,另外还有一个current 属性。这是他们之间的关系。

值得注意的是,不论是否声明继承了接口,在指定类中实现了一个返回IEnumerator 的方法,就可以手动的通过上述的这2个方法和1个属性,进行迭代了;同样的,不论是否有显式的声明,实现了一个返回IEnumerable 的方法,就可以通过foreach 进行迭代了。下面是我推荐的一个Demo:

        static void Main(string[] args)
        {
            testClass myTest = new testClass();
            Console.WriteLine("由于在testClass 已经实现了 GetEnumerator()方法:");
            //直接使用foreach来进行迭代。
            foreach (string a in myTest)
            {
                Console.WriteLine(a);
            }

            //手动迭代
            Console.WriteLine();
            Console.WriteLine("手动迭代:");
            IEnumerator enmuerator = myTest.GetEnumerator();
            while (enmuerator.MoveNext())
            {
                Console.WriteLine(enmuerator.Current.ToString());
            }

            //之所以用手动迭代,是因为不能这样
            //foreach (string a in enmuerator)
            //{
            //    Console.WriteLine(a);
            //}
            //原因是,enmuerator不包含“GetEnumerator”的公共定义
            //foreach无法发现这个定义,但IEnumerable则不同

            Console.WriteLine();
            Console.WriteLine("IEnumerable 还是强悍一些:");
            foreach (string a in myTest.Reverse())
            {
                Console.WriteLine(a);
            }
        }

        class testClass
        {
            string[] cars ={ "BMW Li 5", "Mercedes-benz", "Hong Qi" };

             public IEnumerator GetEnumerator()
            {
                for (int i = 0; i < cars.Length; i++)
                    yield return cars[i];
            }

            public IEnumerable Reverse()
            {
                for (int i = cars.Length-1; i >= 0; i--)
                {
                    yield return cars[i];
                }
            }
        }

在介绍下面的接口之前,我还想补充一个有趣的继承关系:IEnumerable 是基类,接下里有ICollection 继承它,而Ilist 继承ICollection。伴随着这样的继承关系,自然地其实现的方法和属性那是越来越多的。接下来,我们该说说IComparable Vs IComparer .

IComparable 是为指定类型提供了CompareTo() 的方法[必须]来比较自己 .当你将指定的类声明为一个数组时,想用sort() 方法来对数组中的对象进行排序,这时如果已经实现了IComparable 则会自动调用CompareTo() 来进行比较排序。

而IComparer则是为指定类型提供了一种附加的比较机制。IComparer 附加的被实现为一个辅助比较的类,在该辅助类中提供一个Compare 方法[必须]。在指定对象的数组中,调用sort 方法时,只需传递一个该辅助类的实例,即可。由于是附加的,所以可以提供多种含有Compare 方法的辅助类,相比之下,IComparable 只能在指定类中实现一个CompareTo 的方法;从效能方面,2种方法的参数都是传递object。但不同的是,CompareTo只有一个参数。每次进行比较,Compare都需要2倍于前者的“装箱-拆箱”的操作。下面,我还是用一个Demo 来说明问题:

        static void Main(string[] args)
        {
            mobilePhone[] mp = { new mobilePhone("Sony Ericsson",2000M),
                                 new mobilePhone("Nokia",3000M),
                                 new mobilePhone("Samsung",1500M),
                                 new mobilePhone("Shan Zhai",800M),
                                 new mobilePhone("ABC",800M),
                                 new mobilePhone("ACC",700M)
                                };
            //------------
            Console.WriteLine("IComparable Demo:");
            Array.Sort(mp);
            foreach (mobilePhone m in mp)
            {
                Console.WriteLine(m);
            }
            Console.WriteLine();
            //------------
            Console.WriteLine("IComparer-makerASCEcomparer Demo:");
            Array.Sort(mp, mobilePhone.makerASCEcomparer());
            foreach (mobilePhone m in mp)
            {
                Console.WriteLine(m);
            }
            Console.WriteLine();
            //------------
            Console.WriteLine("IComparer-priceASCEcomparer Demo:");
            Array.Sort(mp, mobilePhone.priceASCEcomparer());
            foreach (mobilePhone m in mp)
            {
                Console.WriteLine(m);
            }
            Console.WriteLine();
            //------------
            Console.WriteLine("IComparer-priceDSCEcomparer Demo:");
            Array.Sort(mp, mobilePhone.priceDSCEcomparer());
            foreach (mobilePhone m in mp)
            {
                Console.WriteLine(m);
            }
            Console.WriteLine();
        }

        class mobilePhone:IComparable
        {
            private string maker;
            private decimal price;

            public mobilePhone(string maker,decimal price)
            {
                this.maker = maker;
                this.price = price;
            }

            public string Maker
            {
                get
                {
                    return maker;
                }
                set
                {
                    maker = value;
                }
            }

            public decimal Price
            {
                get
                {
                    return price;
                }
                set
                {
                    price = value;
                }
            }

            int IComparable.CompareTo(object x)
            {
                mobilePhone other = (mobilePhone)x;
                int result = this.price.CompareTo(other.price);
                if (result == 0)
                    this.maker.CompareTo(other.maker);
                return result;
            }

            private class priceASCE : IComparer
            {
                int IComparer.Compare(object x,object y)
                {
                    mobilePhone one = (mobilePhone)x;
                    mobilePhone other = (mobilePhone)y;

                    if (one.Price > other.Price)
                        return 1;
                    else if (one.Price == other.Price)
                        return 0;
                    else
                        return -1;

                }
            }

            public static IComparer priceASCEcomparer()
            {
                return (IComparer)new priceASCE();
            }

            private class priceDSCE : IComparer
            {
                int IComparer.Compare(object x, object y)
                {
                    mobilePhone one = (mobilePhone)x;
                    mobilePhone other = (mobilePhone)y;

                    if (one.Price < other.Price)
                        return 1;
                    else if (one.Price == other.Price)
                        return 0;
                    else
                        return -1;

                }
            }

            public static IComparer priceDSCEcomparer()
            {
                return (IComparer)new priceDSCE();
            }

            private class makerASCE : IComparer
            {
                int IComparer.Compare(object x, object y)
                {
                    mobilePhone one = (mobilePhone)x;
                    mobilePhone other = (mobilePhone)y;

                    int result = one.Maker.CompareTo(other.Maker);
                    return result;
                }
            }

            public static IComparer makerASCEcomparer()
            {
                return (IComparer)new makerASCE();
            }

            public override string ToString()
            {
                return "Mobile Made by " + Maker + ", And Its Price is " + Price.ToString("C");
            }
        }

其实,不得不说,不管是IComparable 还是IComparer 都能实现彼此的功能,IComparer 更符合人类排序比较的思维方式罢了。当然理性的对待问题:首先是要看对效能的需求,其次才是看个人的喜好了。

参考资料:
MSDN——How to use the IComparable and IComparer interfaces in Visual C#

Comment Form

calendar

2009年十一月
« 十   十二 »
 1
2345678
9101112131415
16171819202122
23242526272829
30  

最近评论