ImageVerifierCode 换一换
格式:DOC , 页数:21 ,大小:102.50KB ,
资源ID:7011641      下载积分:10 金币
快捷注册下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

开通VIP
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.zixin.com.cn/docdown/7011641.html】到电脑端继续下载(重复下载【60天内】不扣币)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

开通VIP折扣优惠下载文档

            查看会员权益                  [ 下载后找不到文档?]

填表反馈(24小时):  下载求助     关注领币    退款申请

开具发票请登录PC端进行申请

   平台协调中心        【在线客服】        免费申请共赢上传

权利声明

1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。

注意事项

本文(集合与泛型.doc)为本站上传会员【xrp****65】主动上传,咨信网仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知咨信网(发送邮件至1219186828@qq.com、拔打电话4009-655-100或【 微信客服】、【 QQ客服】),核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载【60天内】不扣币。 服务填表

集合与泛型.doc

1、第2章 集合与泛型 2.1 集合概述 所谓集合是特殊元素们的一种聚合。集合的元素被称为是成员。集合有两个最重要的属性,一个是集合成员都是无序的,另一个则是集合的成员不会出现超过一次。在计算机科学领域内集合扮演着非常重要的角色,但是不把集合包含作为C#语言的一种数据结构。 2.1.1 集合的定义 人们把集合定义成相关成员的无序聚集,而且集合中的成员不会出现超过一次。集合书写成用一对闭合大括号包裹成员列表的形式,例如{0,1,2,3,4,5,6,7,8,9}。只要全部成员只书写一次,就可以按照任意顺序书写集合,所以此前的集合实例还可以写成{9,8,7,6,5,4,3,2,1,0}或其他任意

2、成员组合的形式。 为了使用集合需要知道一些有关集合的定义。 1. 不包含任何成员的集合称为空集合。全域是所有可能成员的集合。 2. 如果两个集合包含完全一样的成员,那么就认为这两个集合相等。 3. 如果第一个集合的全部成员都包含在第二个集合内,就认为第一个集合是第二个集合的子集。 2.1.2 集合的操作 下面描述了在集合上执行的基本操作。 1. 联合:由第一个集合中的所有成员和第二个集合中不包含在第一个集合的成员组成的新集合。 2. 交叉:由既属于第一个集合又属于第二个集合的成员组成的新集合。 3. 差异:由属于第一个集合但不属于第二个集合的成员组成的新集合。 2.2 集合

3、类 ArrayList是与数组相当的集合类。还有其他类型的集合:队列、栈、有序表和哈希表,如下所示: l ArrayList 动态数组 l Queue 队列 l Stack 栈 l BitArray 位数组 l Hashtable 散列表 l SortedList 有序表 集合类位于System.Collections命名空间,集合类可以组合为集合,存储Object类型的元素。 2.3 集合的一种实现 HashTable类是.NET框架类库中较为有效的数据结构之一,它的存取速度较其它类而言要快。下面就以散列表作为存储结构来实现一个集合类,具体代码如下: usin

4、g System; using System.Collections; //集合 public class Set { private Hashtable data; public Set() { data = new Hashtable(); } //添加成员。如果成员不在集合内,则添加到集合中 public void Add(Object item) { if (!data.ContainsValue(item)) { d

5、ata.Add(Hash(item), item); } } //根据成员各字符的ASCII码值计算散列值(在散列表中数据项以键值对形式存在) private string Hash(Object item) { char[] chars; string s = item.ToString(); int hashValue = 0; chars = s.ToCharArray(); for (int i = 0; i <= chars.GetU

6、pperBound(0); i++) { hashValue += (int)chars[i]; } return hashValue.ToString(); } //删除成员 public void Remove(Object item) { data.Remove(Hash(item)); } //成员数量 public int Size { get {

7、 return data.Count; } } //求并集。由第一个集合中的所有成员和第二个集合中不包含在第一个集合的成员组成的新集合。 public Set Union(Set aSet) { Set tempSet = new Set(); foreach (Object hashObject in data.Keys) { tempSet.Add(this.data[hashObject]); } forea

8、ch (Object hashObject in aSet.data.Keys) { if (!(this.data.ContainsKey(hashObject))) { tempSet.Add(aSet.data[hashObject]); } } return tempSet; } //求交集。由既属于第一个集合又属于第二个集合的成员组成的新集合。 public Set Intersection

9、Set aSet) { Set tempSet = new Set(); foreach (Object hashObject in data.Keys) { if (aSet.data.Contains(hashObject)) { tempSet.Add(aSet.data[hashObject]); } } return tempSet; } //判断子集。

10、如果第二个集合大于第一个集合,并且第一个集合中所有成员都包含在第二个集合中,则第一个集合是第二个集合的子集。 public bool Subset(Set aSet) { if (this.Size > aSet.Size) return false; foreach (Object key in this.data.Keys) { if (!(aSet.data.Contains(key))) return false; } return true;

11、 } //求差集。由属于第一个集合但不属于第二个集合的成员组成的新集合。 public Set Difference(Set aSet) { Set tempSet = new Set(); foreach (Object hashObject in data.Keys) { if (!(aSet.data.Contains(hashObject))) { tempSet.Add(data[hashObject]

12、); } } return tempSet; } public override string ToString() { string s = ""; foreach (Object key in data.Keys) s += data[key] + " "; return s; } } class Test { static void Main() { Set setA = n

13、ew Set(); setA.Add("中国"); setA.Add("日本"); setA.Add("美国"); setA.Add("韩国"); Set setB = new Set(); setB.Add("日本"); setB.Add("韩国"); setB.Add("加拿大"); Set setC = new Set(); setC = setA.Union(setB); Conso

14、le.WriteLine("A: " + setA.ToString()); Console.WriteLine("B: " + setB.ToString()); Console.WriteLine("A union B: " + setC.ToString()); setC = setA.Intersection(setB); Console.WriteLine("A intersect B: " + setC.ToString()); setC = setA.Difference(setB)

15、 Console.WriteLine("A diff B: " + setC.ToString()); setC = setB.Difference(setA); Console.WriteLine("B diff A: " + setC.ToString()); if (setB.Subset(setA)) { Console.WriteLine("B is a subset of A"); } else {

16、 Console.WriteLine("B is not a subset of A"); } Console.Read(); } } 运行结果如下: 2.1 泛型概述 泛型(Generic Type)是.NET Framework 2.0的一大特性。泛型的主要思想就是将算法与数据结构完全分离开来,使得一次定义的算法能够作用于多种数据结构,从而实现高度可重用的开发。通过泛型可以定义类型安全的数据结构,而没有必要使用实际的数据类型。这将显著提高性能并得到更高质量的代码,因为可以重用数据处理算法,而没有必要复制类

17、型特定的代码。 泛型是一个很强大的特性,对于集合类而言尤其如此。.NET 1.1中的大多数集合类都基于Object类型。.NET 从2.0开始提供了实现为泛型的新集合类。 泛型不仅限于类,还可用于委托、接口和方法的泛型。 在.NET 2.0之前,不存在泛型,在开发通用容器时,需要通用容器能存储各种类型的实例。在.NET Framework 1.1下,必须使用基于object类型的系统集合类(例如ArrayList,Stack,Queen等),但由于集合类中的项都是Object类型的,因此每次使用时都必须进行装箱拆箱操作,不仅大大降低了程序的性能,而且存在类型安全问题(Object类在编译

18、期间没有类型安全性)。 泛型(Generic Type)的出现较好的解决了上述问题,通过它,可以轻松创建指定类型的集合。泛型集合类不仅是类型安全的,而且使用时不需要进行烦琐的装箱拆箱操作。 泛型是C# 2.0中的新增元素(类似于C++中模板)。这种机制允许将类名作为参数传递给泛型类型,并生成相应的对象。主要利用System.Collections.Generic命名空间下面的List泛型类来创建集合。语法如下:   List ListOfT = new List( ); 其中的"T"就是所要使用的类型,既可以是简单类型,如string、int,也可以是用户自定义类型。

19、 下面看一个具体例子。 using System; using System.Collections.Generic; struct Student { public string sno; //学号 public string sname; //姓名 public int sage; //年龄 public Student(string sno, string sname, int sage) { this.sno = sno; this.sname = sname;

20、 this.sage = sage; } } class SamplesGeneric { static void Main() { //创建Student对象 Student stu1 = new Student("001", "张三", 30); Student stu2 = new Student("002", "李四", 20); Student stu3 = new Student("003", "王五", 50); //创建类型为Student的对

21、象集合 List students = new List(); //将Student对象放入集合 students.Add(stu1); students.Add(stu2); students.Add(stu3); //输出第1学生的姓名 Console.WriteLine(students[0].sname); } } 运行结果如下图: 下面介绍泛型的优点: 1. 性能 泛型的一个主要优

22、点是性能。对值类型使用System.Collections命名空间的集合类,存储数据时需要把值类型转换为引用类型,获取数据时需要把引用类型转换为值类型,即需要进行装箱和拆箱操作。例如,下面例子在存取数据时就进行了装箱拆箱操作。 ArrayList list = new ArrayList(); list.Add(44);   // boxing - convert a value type to a reference type int i1 = (int)list[0];   // unboxing - convert a reference type to a value type

23、 foreach (int i2 in list) { Console.WriteLine(i2);   // unboxing } 装箱和拆箱操作很容易使用,但性能损失比较大,迭代许多项时尤其如此。 System.Collections.Generic命名空间中的List类不使用对象,而是在使用时定义类型。在下面的例子中,List类的泛型类型定义为int,所以int类型在JIT编译器动态生成的类中使用,不再进行装箱和拆箱操作: List list = new List(); list.Add(44);   // no boxing - v

24、alue types are stored in the List int i1 = list[0];   // no unboxing, no cast needed foreach (int i2 in list) { Console.WriteLine(i2); } 2. 类型安全 泛型的另一个特性是类型安全。与ArrayList类一样,如果使用对象,可以在这个集合中添加任意类型。下面的例子在ArrayList类型的集合中添加一个整数、一个字符串和一个MyClass类型的对象: ArrayList list = new ArrayList(); l

25、ist.Add(44); list.Add("mystring"); list.Add(new MyClass()); 如果这个集合使用下面的foreach语句迭代,而该foreach语句使用整数元素来迭代,编译器就会编译这段代码。但并不是集合中的所有元素都可以转换为int,所以会出现一个运行异常: foreach (int i in list) { Console.WriteLine(i); } 错误应尽早发现。在泛型类List中,泛型类型T定义了允许使用的类型。有了List的定义,就只能把整数类型添加到集合中。编译器不会编译这段代码,因为Add(

26、)方法的参数无效: List list = new List(); list.Add(44); list.Add("mystring");   // compile time error list.Add(new MyClass());   // compile time error 3. 代码重用 泛型允许更好地重用代码。泛型类可以定义一次,用许多不同的类型实例化。 例如,System.Collections.Generic命名空间中的List类用一个int、一个字符串和一个MyClass类型实例化: List list = new L

27、ist(); list.Add(44); List stringList = new List(); stringList.Add("mystring"); List myclassList = new List(); myClassList.Add(new MyClass()); 泛型类型可以在一种语言中定义,在另一种.NET语言中使用。 2.2 创建泛型类 泛型最显著的一点就是它参数化了类型,把类型作为参数抽象出来,从而使我们在实际的运用当中能够更好的实现代码的重复利用,同时它提供了更强的类型安

28、全,更高的效率,不过在约束方面,它只支持显式的约束,这样在灵活性方面就显得不是那么好了。泛型之所以能够提供更高的效率是因为泛型在实例化的时候采用了"on-demand"的模式,即按需实例化,发生在JIT(Just In Time)编译时。 下面来看如何定义一个泛型类,很简单,你只需要意识到一点——类型在这里被参数化了: using System; using System.Collections; using System.Collections.Generic; ///

/// 定义一个泛型类,该类有一个类型参数T /// ///

29、 类型参数 class Item { //泛型类的类型参数可用于类成员 public T Value; public Item Next; public Item(T value) { this.Value = value; this.Next = null; } } class Collection : IEnumerable { public Item First = nul

30、l; public Item Last = null; public void Add(T value) { Item newItem = new Item(value); if (this.First == null) { this.First = newItem; this.Last = newItem; } else { this.Last.Next =

31、 newItem; this.Last = newItem; } } public IEnumerator GetEnumerator() { Item current = this.First; while (current != null) { yield return current.Value; current = current.Next; } }

32、IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } class SamplesGeneric { static void Main() { //使用string来实例化Collection类 Collection names = new Collection(); //调用泛型类中的方法 names.Add("张三");

33、 names.Add("李四"); names.Add("王五"); foreach (string name in names) { Console.WriteLine(name); } //同样,也可以使用int来实例化Collection类 Collection ages = new Collection(); //调用泛型类中的方法 ages.Add(25);

34、 ages.Add(34); ages.Add(47); foreach (int age in ages) { Console.WriteLine(age); } Console.Read(); } } 使用泛型类Collection,相当于定义了一个类模板,在具体使用时,需要什么类型即可将它实例化为什么类型,从而实现了代码重用。由于可以用任何类型实例化它,且无需装箱操作,因此比基于Object的非泛型方式获取了更高的性能。如果将Collec

35、tion实例化为int类型,则使用Add ()方法传送非int值,就会出现一个编译错误,所以说它是类型安全的。使用泛型IEnumerable,foreach语句也是类型安全的,如果foreach语句中的变量不是int,也会出现一个编译错误。 2.3 泛型类的特性 在创建泛型类时,需要一些其他C#关键字。例如,不能把null赋予泛型类型。此时,可以使用default关键字。如果泛型类型不需要Object类的功能,但需要调用泛型类上的某些特定方法,就可以定义约束。 1. 默认值 在创建泛型类时,如果需要给类型T指定null,但是,不能把null赋予泛型类型。原因是泛型类型也可以

36、实例化为值类型,而null只能用于引用类型。为了解决这个问题,可以使用default关键字。通过default关键字,将null赋予引用类型,将0赋予值类型。 using System; using System.Collections; using System.Collections.Generic; class SamplesGeneric { public T Value; public SamplesGeneric() { this.Value = default(T);//如果T是值类型则default(T)

37、0;如果T是引用类型则default(T)=null; } } class Test { static void Main() { SamplesGeneric obj1 = new SamplesGeneric(); Console.WriteLine(obj1.Value); SamplesGeneric obj2 = new SamplesGeneric(); Console.WriteLine(obj2

38、Value); Console.Read(); } } 注意: default关键字根据上下文可以有多种含义。switch语句使用default定义默认情况。在泛型中,根据泛型类型是引用类型还是值类型,default关键字用于将泛型类型初始化为null或0。 2. 约束 C#中的泛型只支持显式的约束,因为这样才能保证C#所要求的类型安全,但显式的约束并非时必须的,如果不加约束,泛型类型参数将只能访问System.Object类型中的公有方法。“显式约束”由where子句表达,可以指定“基类约束”,“接口约束”,“构造器约束”,“值类型/引用类型约

39、束”共四种约束。 1、基类约束: class A { public void F1() {} } class B { public void F2() {} } class C where S: A // S继承自A where T: B // T继承自B {  // 可以在类型为S的变量上调用F1,  // 可以在类型为T的变量上调用F2 } 2、接口约束 interface IPrintable { void Print(); } interface IComparable { int CompareTo(T v);} in

40、terface IKeyProvider { T GetKey(); } class Dictionary where K: IComparable where V: IPrintable, IKeyProvider {  // 可以在类型为K的变量上调用CompareTo,  // 可以在类型为V的变量上调用Print和GetKey } 3、构造器约束 class A { public A() { } } class B { public B(int i) { } } class C where T : new(

41、) {  //可以在其中使用T t=new T(); } C c=new C(); //可以,A有无参构造器 C c=new C(); //错误,B没有无参构造器 4、值/引用类型约束 public struct A { } public class B { } class C where T : struct {  // T在这里面是一个值类型 } C c=new C(); //可以,A是一个值类型 C c=new C(); //错误,B是一个引用类型 提示: 在C#中,wh

42、ere子句的一个重要限制是,不能定义必须由泛型类型执行的运算符。运算符不能在接口中定义。在where子句中,只能定义基类、接口和默认构造函数。 3. 继承 如何实现泛型类的继承呢?这里需要满足下面两点中的任何一点即可: 1、泛型类继承中,父类的类型参数已被实例化,这种情况下子类不一定必须是泛型类; 2、父类的类型参数没有被实例化,但来源于子类,也就是说父类和子类都是泛型类,并且二者有相同的类型参数; //如果这样写的话,显然会报找不到类型T的错误 class SubItem : Item { } //正确的写法应该是 class SubItem : Item

43、ing>{ } class SubItem : Item { } class SubItem : Item { } 4. 静态成员 泛型类的静态成员只能在类的一个实例中共享。下面看一个例子。 using System; using System.Collections.Generic; class SamplesGeneric { public static T Value; } class Test { static void Main() { SamplesGene

44、ric.Value = 5; Console.WriteLine(SamplesGeneric.Value); SamplesGeneric.Value = "hello"; Console.WriteLine(SamplesGeneric.Value); Console.Read(); } } 2.4 泛型接口 泛型接口的创建以及继承规则和泛型类是一样的,看下面的代码: using System; using System.Collectio

45、ns.Generic; interface IAdder { T Add(T v1, T v2); } class Adder1 : IAdder { public int Add(int v1, int v2) { return v1 + v2; } } class Adder2 : IAdder { public string Add(string v1, string v2) { return v1 + v2; } }

46、 class SamplesGeneric { static void Main() { Adder1 adder1 = new Adder1(); int sum = adder1.Add(5, 7); Console.WriteLine(sum); Adder2 adder2 = new Adder2(); string str = adder2.Add("hello", "world"); Console.WriteLine(str);

47、 Console.Read(); } } 2.5 泛型方法 我们再来看泛型方法,C#的泛型机制只支持在方法声明上包含类型参数,也即是泛型方法。特别注意的是,泛型不支持在除了方法以外的其他类/接口成员上使用类型参数,但这些成员可以被包含在泛型类型中,并且可以使用泛型类型的类型参数。还有一点需要说的就是,泛型方法可以在泛型类型中,也可以存在于非泛型类型中。下面通过例子看一下泛型方法的声明与调用。 using System; using System.Collections.Generic; class Exchange { //声明一个泛型方法

48、 public static void Swap(ref T x, ref T y) { T temp; temp = x; x = y; y = temp; } } class SamplesGeneric { static void Main() { int i = 4; int j = 5; //在调用泛型方法时,对泛型方法的类型参数实例化 Exchange.Swap(ref

49、 i, ref j); Console.WriteLine("i = {0}, j = {1}", i, j); //泛型方法可以像非泛型方法那样调用 Exchange.Swap(ref i, ref j); Console.WriteLine("i = {0}, j = {1}", i, j); Console.Read(); } } 2.6 泛型委托 再来看一下泛型委托,泛型委托支持在返回值和参数上应用类型参数,下面例子中定义了一个类型参数为T的委托,然后在类中利用委托调

50、用方法: using System; using System.Collections.Generic; delegate string GetString(T value); class SamplesGeneric { public static string Method1(int i) { return i.ToString(); } public static string Methed2(string s) { return s; } st

客服