【黑马程序员】集合框架和自定义集合

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

集合的功能可以通过接口来实现,该接口不仅没有限制我们使用基本的集合类(例如:System.Array),而且我们还可以创建自己的定制集合类。这些集合可以专用于要枚举的对象(即要从中建立集合的对象)。这么做的一个优点是定制的集合类可以是强类型化的,也就是说,从集合中提取项时,我们不需要把它们转换为正确的类型,反而可以直接使用。另一个优点是可以获得专用的方法,比如可以提供获得项子集的快捷方法,或其它一些自己编写的特殊功能。

System.Collections名称空间中的几个接口提供了基本的集合功能:

IEnumerable:可以迭代集合中的项

ICollection:继承于IEnumerable,可以获取集合中项的个数,并能把项复制到一个简单的数组类型中

IList:继承于IEnumerable和ICollection,提供了集合的项列表,并可以访问这些项,以及的其它一些与项列表相关的特殊功能

IDictionary:继承于IEnumerable和ICollection,其功能类似于IList,但提供了可通过键码值而不是索引访问集合的项列表

通过以上接口,我们就自定义一个集合的基本框架。但我们还可以从一个类中派生自己的集合,例如System.Collections.CollectionBase类的许多实现方式,这是推荐使用的方式。CollectonBase类有接口IEnumerable、ICollection和IList,但只提供了一些要求的执行代码,特别是IList的Clear()和RemoveAt()方法,以及ICollection的Count属性。这些功能都需要用户自己用代码去实现。CollectionBase还提供了两个受保护的属性,它们可以访问存储的对象本身:List和InnerList,其中List可以通过IList访问集合的项,InnerList则用于存储项的ArrayList对象。例如:下面的代码中,创建了一个存储Animal对象的集合:

    /// <summary>
    /// 动物集合类(继承自CollectionBase)
    /// </summary>
    public class Animals : CollectionBase
    {
        /// <summary>
        /// 向集合中添加动物对象
        /// </summary>
        /// <param name="newAnimal">要添加的元素</param>
        public void Add(Animal newAnimal)
        {
            List.Add(newAnimal);
        }

        /// <summary>
        /// 从集合中移除某动物对象
        /// </summary>
        /// <param name="oldAnimal">要移除的元素</param>
        public void Remove(Animal oldAnimal)
        {
            List.Remove(oldAnimal);
        }

        public Animals()
        {

        }

        /// <summary>
        /// 实现该集合可以通过索引访问元素
        /// </summary>
        /// <param name="animalIndex">索引值</param>
        /// <returns>集合中该索引处的对象</returns>
        public Animal this[int animalIndex]
        {
            get
            {   //这里需要进行显式数据类型转换,因为Ilist.List属性返回一个System.Object对象
                return (Animal)List[animalIndex];
            }
            set
            {
                List[animalIndex] = value;
            }
        }
main函数中的测试代码如下:
static void Main(string[] args)
        {
            Console.WriteLine("Using custom collection class Animals:");
            Animals animalCollection = new Animals();
            animalCollection.Add(new Cow("Sarah"));
            animalCollection.Add(new Chicken("Roy"));
            foreach (Animal animal in animalCollection)
            {
                Console.WriteLine("New {0} object added to custom collection, " + "Name = {1}", animal.ToString(), animal.Name);
            }
            Console.WriteLine();

            animalCollection[0].Feed();
            animalCollection[1].Feed();

            Console.ReadKey();
        }
在以上代码中,如果Animals类中没有public Animal this[int animalIndex]这个函数,那么测试代码中的animalCollection[0].Feed()和animalCollection[1].Feed()便不能访问访问集合中的元素对象,也就不能调用Animal对象的Feed()方法。在上面的测试代码中,我们从animalCollection集合中取出元素时无需进行转换,因为这个集合中只能存储Animal类型的元素。


以上是通过实现IList接口让集合可以通过索引来访问元素,其实我们还可以通过实现IDictionary接口来允许集合通过键码值访问元素。与上面的方法一样,只不过这个集合需要继承自DictionaryBase,它也实现了IEnumerable和ICollection接口,提供了对任何集合都相同的集合处理功能。DictionaryBase也执行Clear()、Count()和Remove()方法,但不执行RemoveAt()方法,因为RemoveAt()是IList接口上的一个方法。要注意的是在通过Add()向字典集合中添加元素是,要同时添加键码值和元素对象。然后我们就可以通过键码值来访问集合中的元素。



---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章