泛型

     今天上午研究了一个小知识点——泛型,想分享给大家。总结了一下我的研究结果:泛型——集数组和集合优点于一身的好玩意儿。想这样来引出泛型:通过对数组和集合的缺点分析来唤出泛型,鉴于有些同学还没用过数组和集合,我就连数组和集合也稍稍说一下下:

 

实战:

 

       今天周六,下周一我要请小动物(小猫、小狗、小猪...)们吃饭,今明两天报名饭“人”数,我好准备需要多少菜量(注意以上重点:每个小动物都有‘吃’的方法(相同处),但吃的食物不一样(不同处);去吃饭前,要先报名)好,现在开始代码演示:


 父类:动物类

[csharp] view plaincopy
  1. //父类:动物类Animal  
  2.    public  class Animal  
  3.     {  
  4.        protected string name = "";  
  5.        public Animal(string name)//构造函数  
  6.        {  
  7.            this.name = name;  
  8.           
  9.        }  
  10.   
  11.        public Animal()//构造函数  
  12.        {  
  13.            this.name = "";  
  14.        }  
  15.         
  16.        //吃的虚方法  
  17.        public virtual string Eat()  
  18.        {  
  19.            return "";  
  20.        }  
  21.     }  

 


子类:猫类 继承动物类

[csharp] view plaincopy
  1. //子类:猫类  
  2.    class Cat : Animal //继承动物类Animal  
  3.    {  
  4.        //调用父类Animal的构造函数  
  5.        public Cat()  
  6.            : base()   
  7.        { }  
  8.   
  9.        public Cat(string name)  
  10.            : base(name)  
  11.        { }  
  12.   
  13.        //重写父类函数Eat()  
  14.        public override string Eat()  
  15.        {  
  16.            return "我是小猫,我叫" + name + "。 我吃鱼!";  
  17.        }  
  18.    }  


子类:狗类 继承动物类

[csharp] view plaincopy
  1. //子类:狗类  
  2.    class Dog:Animal //狗类继承动物类Animal  
  3.    {  
  4.        //调用父类Animal的构造函数  
  5.        public Dog()  
  6.            : base()  
  7.        { }  
  8.   
  9.        public Dog(string name)  
  10.            : base(name)  
  11.        { }  
  12.   
  13.        //Eat()函数重写  
  14.        public override string Eat()  
  15.        {  
  16.            return "我是小狗,我叫" + name + "。 我吃骨头!";  
  17.   
  18.        }  
  19.          
  20.    }  


子类:猪类 继承动物类

[csharp] view plaincopy
  1. //子类:猪类  
  2.    class Pig:Animal //猪类继承动物类Animal  
  3.    {  
  4.        //调用父类Animal的构造函数  
  5.        public Pig()  
  6.            : base()  
  7.        { }  
  8.   
  9.        public Pig(string name)  
  10.            : base(name)  
  11.        { }  
  12.   
  13.        //重写父类Animal的Eat()函数  
  14.        public override string Eat()  
  15.        {  
  16.            return "我是小猪,我叫" + name + "。 我吃馒头!";  
  17.   
  18.        }  
  19.    }  

 

组合实现:

 

客户端代码:

 

[csharp] view plaincopy
  1. private Animal[] arrayAnimal;//声明一个动物数组  
  2.   
  3.        //点击“报名吃饭”按钮  
  4.        private void btnSignUp_Click(object sender, EventArgs e)  
  5.        {  
  6.            arrayAnimal = new Animal[4];//实例化最多可报名4个的动物数组对象  
  7.              
  8.            //报名吃饭的对象:猫‘小丽’,狗‘小强’,猪‘小懒’,猫‘小红’  
  9.            arrayAnimal[0] = new Cat("小丽");  
  10.            arrayAnimal[1] = new Dog("小强");  
  11.            arrayAnimal[2] = new Pig("小懒");  
  12.            arrayAnimal[3] = new Cat("小红");  
  13.   
  14.        }  
  15.   
  16.        //点击“吃饭"按钮  
  17.        private void btnEat_Click(object sender, EventArgs e)  
  18.        {  
  19.            foreach (Animal item in arrayAnimal)//遍历数组,让所有报名吃饭的都Eat()  
  20.            {  
  21.                MessageBox.Show(item.Eat());  //各自调用各自的Eat()函数,来实现吃饭  
  22.            }  
  23.        }  


分析一下客户端代码:

    我们定义了一个4个长度的数组,这就限制了只能有4个动物可以报名去吃饭,多了就不允许了,少了也不行,很不合理,不灵活。

 

数组优点:数组在内存中连续存储,因此可以快速容易的从头到尾遍历元素,可以快速修改元素等等。缺点:1)创建时必须要指定数组变量的大小;(2)在两个元素之间添加元素很困难

 

   鉴于数组的这两个缺点,我们用集合来实现:

 

客户端代码:

 

[csharp] view plaincopy
  1. using System.Collections;//增加集合命名空间  
  2.   
  3. IList arrayAnimal;//声明集合变量  
  4.   
  5.        //点击“报名吃饭”按钮  
  6.        private void btnSignUp_Click(object sender, EventArgs e)  
  7.        {  
  8.            arrayAnimal = new ArrayList();//实例化ArrayList对象(注意:与数组不同之处是 没有指定arrayAnimal的大小)  
  9.   
  10.            arrayAnimal.Add(new Cat("小丽"));  
  11.            arrayAnimal.Add(new Dog("小强"));  
  12.            arrayAnimal.Add(new Pig("小懒"));  
  13.            arrayAnimal.Add(new Cat("小红"));       
  14.       
  15.        }  
  16.   
  17.        //点击“吃饭”按钮  
  18.        private void btnEat_Click(object sender, EventArgs e)  
  19.        {  
  20.            foreach (Animal item in arrayAnimal)//遍历ArrayList集合  
  21.            {  
  22.                MessageBox.Show(item.Eat());//各自实现各自的Eat()函数,来实现吃饭  
  23.            }  
  24.        }  


再分析客户端代码:

    与数组相比,集合优点:

    (1)不用事先设置大小,它可以根据使用大小按需增加,也就是说如果明天 “狗小胖”和“猫小兰”也要报名去吃饭,那么可以直接增arrayAnimal.Add(newDog(胖"));arrayAnimal.Add(new Cat("小兰"));

    (2)可以随意地添加、插入或移除元素,比数组方便灵活。比如:猫小丽下周一要去相亲,去不了啦。arrayAnimal.RemoveAt(0);虽说集合的确有着数组没有的方便和灵活,但是,问题又来了——我邀请的是动物去吃饭,如果在报名期间有其他种类(比方说“人”)也报名去吃饭:arrayAnimal.Add(new Person("张三")); 不想接受他,他也来了,怎么办?

 注意:Person类不继承Animal类,它是一个单独的类,这里没有写出来)

 

集合ArrayList的不足:

    ArrayList不管什么对象都是接受的,因为在它眼里所有元素都欧式Object,这就使得如果你‘arrayAnimal.Add(new Person("张三"));’或者‘arrayAnimal.Add(123);’‘arrayAnimal.Add("Good Morning");’在编译时都是没有问题的,但在执行时,‘foreach(Animal item in arrayAnimal)’需要明确集中的元素的类型不匹配错误,换句话说,ArrayList不是类型安全的。还有就是ArrayList对于存放值类型的数据,比如int、string(string是一种拥有值类型特点的特殊引用类型)或者结构struct的数据,用ArrayList就意味着都需要将值类型装箱为Object对象,使用集合元素时,还需要执行拆箱操作,这就带来了很大的性能损耗。

  

装箱:

   把值类型打包到Object引用类型的一个实例中。比如整型变量i被“装箱”并赋值给对象obj:int i=123;

 Object obj=(object) i; //装箱

 

 

拆箱:

   从对象中提取值类型。上例中对象obj拆箱并将其赋值给整型变量i:Obj=123;i=(int)obj;  //拆箱

 

   相对简单的赋值而言,装箱和拆箱过程需要进行大量的计算。对值类型进行装箱时,必须分配并构造一个全新的对象。其次,拆箱所需的强制转换也需要进行大量的计算。总之,装箱拆箱是耗费资源和时间的。而ArrayList集合在使用值类型数据时,其实就是不断地做装箱和拆箱的工作,这显然很糟糕、很影响性能。哎呀,数组收事先设置大小的控制,又不可随意添加、移除;集合吧又什么类型都接受,并且不断装拆箱影响性能。该怎么办呢??哈哈泛型来喽。。。

 

泛型(概念):

   具有有占位符(类型参数)的类、结构、接口和方法,这些占位符是类、结构、接口和方法所存储或使用的一个或多个类型的占位符,泛型集合类可以将类型参数用作它所存储的对象的类型的占位符;类型参数作为其字段的类型和器方法的参数类型出现。概念很抽象。

 

其实关键就是:给集合加上类型,让该集合只能接受某一类型的对象。关键就是:在IList和List后面加‘<T>’,这个‘T’及时需要指定的集合的数据或对象类型

 

泛型实现:

 

客户端代码:

[csharp] view plaincopy
  1.    
  2. using System.Collections.Generic;//增加泛型集合命名空间  
  3.   
  4.   
  5. //声明一个泛型集合变量,用接口IList,注意:IList<Animal>表示此集合变量只能接受Animal类型,其他不可以。比较与声明集合变量IList arrayAnimal;的不同——是不是多了一个<Animal>,这个Animal就是这个集合能接受的对象类型  
  6.         IList<Animal> arrayAnimal;    
  7.   
  8.         //点击“报名吃饭”按钮  
  9.         private void btnSignUp_Click(object sender, EventArgs e)  
  10.         {  
  11.             arrayAnimal = new List<Animal>();//实例化List对象,此时也要指定List<T>的‘T’是Animal  
  12.   
  13.             arrayAnimal.Add(new Cat("小丽"));  
  14.             arrayAnimal.Add(new Dog("小强"));  
  15.             arrayAnimal.Add(new Pig("小懒"));  
  16.             arrayAnimal.Add(new Cat("小红"));  
  17.               
  18.         }  
  19.   
  20.         //点击“吃饭”按钮  
  21.         private void btnEat_Click(object sender, EventArgs e)  
  22.         {  
  23.             foreach (Animal item in arrayAnimal)//遍历泛型集合  
  24.             {  
  25.                 MessageBox.Show(item.Eat());//各自实现各自的Eat()函数,来实现吃饭  
  26.             }  
  27.         }  


 

如果现在‘张三’再想报名arrayList.Add(new Person("张三"));会有什么后果?嘿嘿,报错呗,因为泛型集合arrayAnimal不接受出Animal类型(或Animal子类型)以外的类型对象。

 

泛型的优点:

   其实List和ArrayList在功能上是一样的,不同之处:泛型在声明和实例化时都需要指定内部项的数据或对象类型,这就避免了集合的类型不安全问题和拆装箱的性能问题了。

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值