集合就像是一种容器,是用于存储、获取、操作对象的容器。如果集合中不使用泛型,意味着集合中可以添加任意类型的对象。当用户需要具体用到某一个类型时,必须强制进行类型转换才可以得到,但是这样就可能引发异常。
一、认识集合
1、集合类的概念
集合(Collection)类是专门用于数据存储和检索的类。
2、集合类的特点
(1)集合类定义为System.Collections或System.Collections.Generic命名空间的一部分。
(2)大多数集合类都派生自ICollection、IComparer、IEnumerable、IList、IDictionary和IDictionaryEnumerator接口以及它们的等效泛型接口。
(3)使用泛型集合类可以提供更高的类型安全性,在某些情况下还可以提供更好的性能,尤其是在存储值类型时,这些优势会体现得更明显。
二、常用集合类型
常用的集合类型有动态数组(ArrayList类)、堆栈(Stack类)、Queue类和Hashtable类。
1、动态数组
动态数组(ArrayList)代表了可被单独索引的对象的有序集合。它基本上可以替代一个数组。但是,与数组不同的是,用户可以使用索引在指定的位置添加和移除项目,动态数组会自动重新调整它的大小。它也允许在列表中进行动态内存分配、增加、搜索、排序各项。
1、ArrayList类的方法和属性
属性 | 描述 |
Capacity | 获取或设置ArrayList可以包含的元素个数 |
Count | 获取ArrayList中实际包含的元素个数 |
IsFixedSize | 获取一个值,表示ArrayList是否具有固定大小 |
IsReadOnly | 获取一个值,表示ArrayList是否只读 |
Item | 获取或设置指定索引处的元素 |
序号 | 方法名&描述 |
1 | public virtual int Add(object value);在ArrayList的末尾添加一个对象 |
2 | public virtual void AddRange(ICollection c);在ArrayList的末尾添加Icollection的元素 |
3 | public virtual void Clear();从ArrayList中移除所有的元素 |
4 | public virtual bool Contains(object item);判断某个元素是否在ArrayList中 |
5 | public virtual ArrayList GetRange(int index, int count);返回一个ArrayList,表示源ArrayList中元素的子集 |
6 | public virtual int IndexOf(object);返回某个值在ArrayList中第一次出现的索引,索引从零开始。 |
7 | public virtual void Insert(int index, object value);在ArrayList的指定索引处,插入一个元素 |
8 | public virtual void InsertRange(int index, ICollection c);在ArrayList的指定索引处,插入某个集合的元素 |
9 | public virtual void Remove(object obj);从ArrayList中移除第一次出现的指定对象 |
10 | public virtual void RemoveAt(int index);移除ArrayList的指定索引处的元素 |
11 | public virtual void RemoveRange(int index, int count);从ArrayList中移除某个范围的元素 |
12 | public virtual void Reverse(); 逆转ArrayList中元素的顺序 |
13 | public virtual void SetRange(int index, ICollection c); 复制某个集合的元素到ArrayList中某个范围的元素上 |
14 | public virtual void Sort(); 对ArrayList中的元素进行排序 |
15 | public virtual void TrimToSize(); 设置容量为ArrayList中元素的实际个数 |
2、ArrayList类中元素的添加
编写程序,创建ArrayList实例,使其固定大小为5,通过Add方法对其添加5个元素,再通过AddRange方法对其添加一个数组,然后遍历所有数元素。
using System;
using System.Collections; //在命名空间进行引用
namespace Project1
{
class Program
{
static void Main(string[] args)
{
ArrayList al = new ArrayList(5); //创建ArrayList的实例,使其固定大小为5
// ArrayList的好处是,长度不固定,类型随意
//数组的长度是固定的,不能更改的,类型单一,只能为其中的一种
Console.WriteLine("------------Count属性----------------");
Console.WriteLine("查看ArrayList中实际包含的元素个数:{0}",al.Count);
Console.WriteLine("-------------Add方法-----------------");
//Console.WriteLine("al初始化之后有{0}个元素",al.Count);//使用Count属性,查看ArrayList中实际包含的元素个数。
//Add方法用于向ArrayList中添加单个元素,每次只能添加一个
al.Add(110); //整数类型
al.Add('M'); //字符类型
al.Add("HelloWorld"); //string类型
al.Add(3.14); //浮点类型
al.Add(24L); //长整型
Console.WriteLine("使用Add方法添加5个元素之后,元素的个数:",al.Count);
Console.WriteLine("------------AddRange方法--------------");//AddRange方法用于一次性向ArrayList中添加多个元素,可以是一个数组
string[] myStringAL = { "张三", "李四", "王五", "赵六" };//定义字符串数组
al.AddRange(myStringAL);
Console.WriteLine("使用AddRange方法添加4个元素后,元素的个数:{0}",al.Count);
Console.WriteLine("--------------遍历集合----------------");
//遍历集合元素
//引用类型 string object类是所有类型的基类
foreach (object outstring in al) //首先定义一个任意类型的变量object,
{
Console.Write(outstring+"\t"); //按行来输出
}
Console.WriteLine();
}
}
}
3、ArrayList类中元素的删除
using System;
using System.Collections; //在命名空间进行引用
namespace Project2
{
class Program
{
static void Main(string[] args)
{
//元素的删除有四种方法
//Remove()
ArrayList al = new ArrayList(); //实例化对象
al.Add("小组评分:");
al.Add(88.5);
al.Add("小组成员:");
string[] myStringAL = { "张三", "李四", "王五", "赵六" };
al.AddRange(myStringAL);
foreach (object outArry in al)
{
Console.Write(outArry+"\t");
}
Console.WriteLine("\n------------Remove方法----------------");//Remove(值)
Console.WriteLine("指定对象,移除张三");
al.Remove("张三");
foreach (object outArry in al)
{
Console.Write(outArry + "\t");
}
Console.WriteLine("\n-----------RemoveAt方法---------------");//RemoveAt(索引值)
Console.WriteLine("指定索引值,移除李四");
al.RemoveAt(3);
foreach (object outArry in al)
{
Console.Write(outArry + "\t");
}
Console.WriteLine("\n-----------RemoveRange方法------------");//RemoveRange(开始索引值,要删除的个数)
Console.WriteLine("指定某个范围,移除王五和赵六");
al.RemoveRange(3, 2);//从第三元素开始,删除两个元素
foreach (object outArry in al)
{
Console.Write(outArry + "\t");
}
Console.WriteLine("\n-----------Clear方法------------");
Console.WriteLine("清除所有元素");
al.Clear();
foreach (object outArry in al)
{
Console.Write(outArry + "\t");
}
Console.WriteLine();
}
}
}
4、ArrayList类中元素的遍历和查找
using System;
using System.Collections;
namespace Project3
{
class Program
{
static void Main(string[] args)
{
ArrayList al = new ArrayList();
al.Add("数组:");
int[] alInArry = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
al.AddRange(alInArry);
al.Add("字符串:");
string[] alStringArry = { "张三", "李四", "王五", "赵六","李四" };
al.AddRange(alStringArry);
Console.WriteLine("------------遍历元素----------------");
foreach (object outArry in al)
{
Console.Write(outArry+" ");
}
Console.WriteLine("\n------------查找元素----------------");
Console.WriteLine("\n-----------IndexOf方法--------------");
//IndexOf(要查找的元素),返回一个首次出现的索引整型值,如果查找不到,返回-1
Console.WriteLine(al.IndexOf("李四"));
Console.WriteLine("\n----------LastIndexOf方法-----------");
//LastIndexOf(要查找的元素),返回一个最后一次出现的索引整型值,否则返回-1
Console.WriteLine(al.LastIndexOf("李四"));
}
}
}
2、堆栈(Stack)类
堆栈(Stack)代表了一个后进先出的对象集合。当用户需要对各项进行后进先出的访问时,则使用堆栈。当用户在列表中添加一项时,称为推入元素,当用户从列表中移除一项时,称为弹出元素。
序号 | 方法名&描述 |
1 | public virtual void Clear(); 从Stack中移除所有的元素 |
2 | public virtual bool Contains(object obj); 判断某个元素是否在Stack中 |
3 | public virtual object Peek(); 返回在Stack的项目的对象,但不移除它 |
4 | public virtual object Pop(); 移除并返回在Stack的顶部的对象 |
5 | public virtual void Push(object obj); 向Stack的顶部添加一个对象 |
6 | public virtual object[] ToArray(); 复制Stack到一个新的数组中 |
编写程序,实现堆栈的进出
代码如下:
using System;
using System.Collections;
namespace Project4
{
class Program
{
static void Main(string[] args)
{
Stack st = new Stack(); //实例化st的对象
Console.WriteLine("------------Push方法----------------");
Console.WriteLine("向堆栈的顶部添加四个对象");
st.Push('a');
st.Push('b');
st.Push('c');
st.Push('d');
Console.WriteLine("------------遍历Stack---------------");
foreach (char c in st)
{
Console.Write(c + " ");
}
Console.WriteLine();
Console.WriteLine("向堆栈的顶部添加两个对象");
st.Push('V');
st.Push('H');
foreach (char c in st)
{
Console.Write(c + " ");
}
Console.WriteLine("\n------------Peek方法----------------");
Console.WriteLine("堆栈顶部的对象:{0}",st.Peek());
Console.WriteLine("--------------Pop方法---------------");
Console.WriteLine("移除堆栈顶部的对象:{0}",st.Pop());
foreach (char c in st)
{
Console.Write(c + " ");
}
Console.WriteLine("\n移除堆栈顶部的对象:{0}", st.Pop());
foreach (char c in st)
{
Console.Write(c + " ");
}
Console.WriteLine();
}
}
}
运行结果如下:
------------Push方法----------------
向堆栈的顶部添加四个对象
------------遍历Stack---------------
d c b a
向堆栈的顶部添加两个对象
H V d c b a
------------Peek方法----------------
堆栈顶部的对象:H
--------------Pop方法---------------
移除堆栈顶部的对象:H
V d c b a
移除堆栈顶部的对象:V
d c b a
3、队列(Queue)类
队列(Queue)代表了一个先进先出的对象集合。当需要对各项进行先进先出的访问时,则使用队列。在列表中添加一项时,称为入队,从列表中移除一项时,称为出队。
序号 | 方法名&描述 |
1 | public virtual void Clear();从Queue中移除所有的元素 |
2 | public virtual bool Contains(object obj);判断某个元素是否在Queue中 |
3 | public virtual object Dequeue();移除并返回在Queue的开头的对象 |
4 | public virtual void Enqueue(object obj); 向Queue的末尾添加一个对象 |
5 | public virtual object[] ToArray(); 复制Queue到一个新的数组中 |
6 | public virtual void TrimToSize(); 设置容量为Queue中元素的实际个数 |
编写程序 ,实现队列的进出。
using System;
using System.Collections;
namespace Project5
{
class Program
{
static void Main(string[] args)
{
Queue q = new Queue(); //创建一个队列
Console.WriteLine("------------Enqueue方法----------------");
Console.WriteLine("向队列的末尾依次添加对象");
q.Enqueue('a');
q.Enqueue('b');
q.Enqueue('c');
q.Enqueue('d');
Console.WriteLine("--------------遍历队列-----------------");
foreach (char c in q)
{
Console.Write(c + " ");
}
Console.WriteLine("\n向队列的末尾再添加两个对象");
q.Enqueue('V');
q.Enqueue('H');
foreach (char c in q)
{
Console.Write(c + " ");
}
Console.WriteLine();
Console.WriteLine("------------Dequeue方法----------------");
Console.WriteLine("移除队列开头的两个对象");
char ch = (char)q.Dequeue();
Console.WriteLine("移除开头第一个对象: {0}", ch);
ch = (char)q.Dequeue();
Console.WriteLine("移除开头第二个对象: {0}", ch);
Console.WriteLine("--------------遍历队列-----------------");
foreach (char c in q)
{
Console.Write(c + " ");
}
Console.WriteLine();
}
}
}
运行结果如下:
------------Enqueue方法----------------
向队列的末尾依次添加对象
--------------遍历队列-----------------
a b c d
向队列的末尾再添加两个对象
a b c d V H
------------Dequeue方法----------------
移除队列开头的两个对象
移除开头第一个对象: a
移除开头第二个对象: b
--------------遍历队列-----------------
c d V H
4、哈希表(Hashtable)类
Hashtable被称作哈希表,该哈希表将映射到相应的值。用于处理和表现类似key/value的键值对,其中,key通常可用来快速查找,同时key是区分大小写的;value用于存储对应于key的值。
Hashtable中key/value键值对均为object类型,所以Hashtable可以支持任何类型的key/value键值对。Hashtable中的每个元素是一个存储在DictionaryEntry对象中的键值对。
1、Hashtable类的方法和属性
属性 | 描述 |
Count | 获取Hashtable中包含的键值对个数 |
IsFixedSize | 获取一个值,表达Hashtable是否具有固定大小 |
IsReadOnly | 获取一个值,表达Hashtable是否只读 |
Item | 获取或设置与指定的键相关的值 |
Keys | 获取一个ICollection,包含Hashtable中的键 |
Values | 获取一个ICollection,包含Hashtable中的键 |
序号 | 方法名&描述 |
1 | public virtual void Add(object key, object, value);向Hashtable添加一个带有指定的键和值的元素 |
2 | public virtual void Clear();从Hashtable中移除所有的元素 |
3 | public virtual void ContainsKey(object key);判断Hashtable是否包含指定的键 |
4 | public virtual void ContainsValue(object value);判断Hashtable是否包含指定的值 |
5 | public virtual void Remove(object key);从Hashtable中移除带有指定的键的元素 |
2、Hashtable类中元素的添加
编写程序,新建一个Hashtable对象,向其中添加四个元素。
using System;
using System.Collections;
namespace Project6
{
class Program
{
static void Main(string[] args)
{
Hashtable ht = new Hashtable();
Console.WriteLine("------------元素添加方法一----------------");
ht.Add(1, "星期一");
ht.Add(2, "星期二");
ht.Add(3, "星期三");
ICollection key = ht.Keys; //获取键值
foreach (object k in key)
{
Console.WriteLine(k + ": " + ht[k]);
}
//用此种方法对Hashtable去增加元素时,应该注意:
//如果对应的键key,存值,只达到一种重新赋值的结果
//如果不存在,才会增加对应的键值对
Console.WriteLine("------------元素添加方法二----------------");
ht[4] = "星期四";
ht[1] = "星期五";
foreach (object k in key)
{
Console.WriteLine(k + ": " + ht[k]);
}
Console.WriteLine("---------------Count属性------------------");
Console.WriteLine("哈希表包含键值对的个数:{0}", ht.Count);
}
}
}
运行结果如下:
------------元素添加方法一----------------
3: 星期三
2: 星期二
1: 星期一
------------元素添加方法二----------------
4: 星期四
3: 星期三
2: 星期二
1: 星期五
---------------Count属性------------------
哈希表包含键值对的个数:4
3、Hashtable元素的遍历
数组的遍历通常都采用的是for循环语句,但是对于集合的遍历都是采用foreach语句。在C#语言中的foreach语句需要集合中每个元素的类型。对于IDictionary接口是键/值对的非泛型集合的基接口,而每个元素都是键/值对,并存储在DictionaryEntry对象中,因此元素类型即不是键的类型,也不是值的类型,而是DictionaryEntry类型。
编写程序 ,新建Hashtable的对象,向其中添加四个元素,使用foreach进行遍历。
using System;
using System.Collections;
namespace Project7
{
class Program
{
static void Main(string[] args)
{
Hashtable ht = new Hashtable();
ht.Add(1, "星期一");
ht.Add(2, "星期二");
ht.Add(3, "星期三");
ht[4] = "星期四";
Console.WriteLine("-------------方法一------------");
foreach (DictionaryEntry obj in ht)
{
Console.WriteLine("键为:{0};值为:{1}",obj.Key,obj.Value);
}
Console.WriteLine("-------------方法二------------");
foreach (object obj in ht.Keys) //键的集合
{
Console.WriteLine("键为:{0};值为:{1}", obj, ht[obj]);
}
}
}
}
运行结果如下:
-------------方法一------------
键为:4;值为:星期四
键为:3;值为:星期三
键为:2;值为:星期二
键为:1;值为:星期一
-------------方法二------------
键为:4;值为:星期四
键为:3;值为:星期三
键为:2;值为:星期二
键为:1;值为:星期一
4、Hashtable元素的删除
编写程序,新建Hashtable的对象,向其中添加四个元素,然后进行删除。
using System;
using System.Collections;
namespace Project8
{
class Program
{
static void Main(string[] args)
{
Hashtable ht = new Hashtable();
ht.Add("01", "星期一");
ht.Add("02", "星期二");
ht.Add("03", "星期三");
ht.Add("04", "星期四");
foreach (DictionaryEntry de in ht)
{
Console.WriteLine("键为{0};值为{1}",de.Key,de.Value);
}
Console.WriteLine("-------------Remove方法------------");
Console.WriteLine("移除哈希表中指定的键的元素");
ht.Remove("04");
foreach (DictionaryEntry de in ht)
{
Console.WriteLine("键为{0};值为{1}", de.Key, de.Value);
}
Console.WriteLine("\n-------------Clear方法------------");
Console.WriteLine("从 Hashtable 中移除所有的元素");
ht.Clear();
foreach (DictionaryEntry de in ht)
{
Console.WriteLine("键为{0};值为{1}", de.Key, de.Value);
}
}
}
}
运行结果如下:
键为02;值为星期二
键为03;值为星期三
键为04;值为星期四
键为01;值为星期一
-------------Remove方法------------
移除哈希表中指定的键的元素
键为02;值为星期二
键为03;值为星期三
键为01;值为星期一
-------------Clear方法------------
从 Hashtable 中移除所有的元素
5、Hashtable元素的查找
Hashtable中键与值成对存在,键是唯一的,不能重复查找元素的时候,用户往往是依据键去查找值的。
using System;
using System.Collections;
namespace Project9
{
class Program
{
static void Main(string[] args)
{
Hashtable ht = new Hashtable();
ht.Add(1, "星期一");
ht.Add(2, "星期二");
ht.Add(3, "星期三");
ht.Add(4, "星期四");
foreach (DictionaryEntry de in ht)
{
Console.WriteLine("键为{0};值为{1}", de.Key, de.Value);
}
Console.WriteLine("-------------ContainsKey------------");
Console.WriteLine("判断 Hashtable 是否包含的键:3");
if (ht.ContainsKey(3)) Console.WriteLine("存在该键");
else Console.WriteLine("不存该键");
Console.WriteLine("------------ContainsValue-----------");
Console.WriteLine("判断 Hashtable 是否包含的值:{0}",ht[1]);
if (ht.ContainsValue("星期一")) Console.WriteLine("存在改值");
else Console.WriteLine("不存该值");
}
}
}
运行结果如下:
键为4;值为星期四
键为3;值为星期三
键为2;值为星期二
键为1;值为星期一
-------------ContainsKey------------
判断 Hashtable 是否包含的键:3
存在该键
------------ContainsValue-----------
判断 Hashtable 是否包含的值:星期一
存在改值
三、泛型
泛型(Generics)是将类型作为参数传递给类、结构、接口和方法,这些参数通常被称为占位符、是类、结构、接口和方法所存储或使用的一个或多个类型的占位符。
1、泛型的概述
泛型是允许用户延迟编写类或方法中的编程元素的数据类型的规范,直到实际在程序中使用它的时候再进行确认。换句话说,泛型允许用户编写一个可以与任何数据类型一起工作的类或方法。
用户可以通过数据类型的替代参数编写类或方法的规范。当编译器遇到类的构造函数或方法的函数调用时,它会生成代码来处理指定的数据类型。
编写程序,创建一个泛型类MyGenericArray,直到实际使用类中成员时,再确定成员的数据类型。
using System;
namespace Project10
{
public class MyGenericArray<T> //创建泛型类
{
//定义未知类型的数组array
private T[] array;
//构造函数用于处理指定的数据类型
public MyGenericArray(int size)
{
array = new T[size + 1];
}
//获取数组元素
public T GetItem(int index)
{
return array[index];
}
//为数组元素赋值
public void SetItem(int index, T value)
{
array[index] = value;
}
}
class Program
{
static void Main(string[] args)
{
// 声明一个整型数组
MyGenericArray<int> intArray = new MyGenericArray<int>(5);
// 设置值
for (int arr = 0; arr < 5; arr++)
{
intArray.SetItem(arr, arr * 2);
}
// 获取值
for (int arr = 0; arr < 5; arr++)
{
Console.Write(intArray.GetItem(arr) + " ");
}
Console.WriteLine();
// 声明一个字符数组
MyGenericArray<char> charArray = new MyGenericArray<char>(5);
// 设置值
for (int arr = 0; arr < 5; arr++)
{
charArray.SetItem(arr, (char)(arr + 97));
}
// 获取值
for (int arr = 0; arr < 5; arr++)
{
Console.Write(charArray.GetItem(arr) + " ");
}
Console.WriteLine();
}
}
}
运行结果:
2、泛型的特点
泛型是一种增加程序功能的技术,具体表现在以下几个方面。
(1)泛型为开发者提供了一种高性能的编程方式,能够提高代码的重用性,并允许开发者编写非常有效的解决方案。
(2)使用泛型可以提高性能,其中一个显著的改进是.NET框架组件,不会在值类型上使用装箱(Boxing);使用泛型类的另一个令人惊讶的特性是可以跟踪强数据类型定义。
(3)泛型类和泛型方法同时具备可重用性、类型安全和效率高等特点,它通常用在集合或者在集合上运行的方法中。
(4)用户可以对泛型类进行约束以访问特定数据类型的方法。
(5)关于泛型数据类型中使用的类型的信息可在运行时通过使用反射获取。
(6)用户可以创建泛型集合类。.NET框架类库在System.Collections.Generic命名空间中包含一些新的泛型集合类。用户可以使用这些泛型集合类来替代System.Collections中的集合类。
3、类型参数T
类型参数T是用来定义泛型类时的占位符,T并不是一种类型,它仅代表某种可能的类型。在定义时,T出现 的位置可以在使用时用任何类型来代替。
编写程序,使用类型参数T来代表各种数据类型。
using System;
using System.Collections.Generic;
namespace Project11
{
//定义泛型类
public class TGeneric<T>
{
void Exp(T input)
{
}
}
//自定义类
public class MyClass
{ }
class Program
{
static void Main(string[] args)
{
//实例化TGeneric的对象为char、int、string类型
TGeneric<char> charTG = new TGeneric<char>();
Console.WriteLine("实例化类型为char的TGeneric的charTG成功");
TGeneric<int> intTG = new TGeneric<int>();
Console.WriteLine("实例化类型为int的TGeneric的intTG成功");
TGeneric<string> stringTG = new TGeneric<string>();
Console.WriteLine("实例化类型为string的TGeneric的stringTG成功");
//实例化TGeneric的对象为MyClass类类型
TGeneric<MyClass> classTG = new TGeneric<MyClass>();
Console.WriteLine("实例化类型为class的TGeneric的classTG成功");
}
}
}
运行结果:
4、泛型集合
泛型集合是可以将类型参数用作它所存储的对象的类型的点位符。
1、创建泛型集合
主要利用System.Collections.Generic命名空间下面的List<T>泛型类创建集合。
其语法格式如下:
List<T> list = new List<T>();
其中,尖括号就是一个泛型的标识,而T是一个类型的总称,也就是type,它既可以是简单类型,如string、int,也可以是用户自定义类型。list是泛型集合的名称。
编写程序,创建一个泛型集合,并为该集合添加元素。
using System;
using System.Collections.Generic;
namespace Project12
{
class Person
{
private string _name; //姓名
private int _score; //年龄
//创建Person对象
public Person(string Name, int Score)
{
this._name = Name;
this._score = Score;
}
//姓名
public string Name
{
get { return _name; }
}
//年龄
public int Score
{
get { return _score; }
}
}
class Program
{
static void Main(string[] args)
{
//创建Person对象
Person p1 = new Person("张三", 90);
Person p2 = new Person("李四", 80);
Person p3 = new Person("王五", 70);
//创建类型为Person的对象集合
List<Person> list = new List<Person>();
//将Person对象放入集合
list.Add(p1);
list.Add(p2);
list.Add(p3);
//输出第2个人的姓名和成绩
Console.WriteLine(list[1].Name + "\t" + list[1].Score);
}
}
}
运行结果:
2、List类的作用
编程程序,将数组元素放入到List创建的泛型集合中,并调用各种方法对数组元素进行操作。
using System;
using System.Collections.Generic; //泛型的英文名称Generic
using System.Collections; //ArrayList
namespace Project13
{
class Program
{
static void Main(string[] args)
{
//泛型结构的声明,和初始化的一个过程,list是泛型的名称
List<int> list = new List<int>();
//声明之后就于ArrayList添加元素一样
list.Add(2);
list.Add(4);
int[] arrInt = { 1, 2, 3, 4, 5, 6 };
list.AddRange(arrInt); //添加一个数组
Console.WriteLine("\n-------------遍历元素------------");
for (int i = 0; i < list.Count; i++)
{
Console.Write(list[i] + " ");
}
Console.WriteLine("\n-------------清除元素------------");
list.Remove(2);
for (int i = 0; i < list.Count; i++)
{
Console.Write(list[i] + " ");
}
Console.WriteLine("\n-------------倒叙元素------------");
list.Reverse();
for (int i = 0; i < list.Count; i++)
{
Console.Write(list[i] + " ");
}
Console.WriteLine("\n-------------排序元素------------");
list.Sort();
for (int i = 0; i < list.Count; i++)
{
Console.Write(list[i] + " ");
}
Console.WriteLine();
}
}
}
运行结果:
-------------遍历元素------------
2 4 1 2 3 4 5 6
-------------清除元素------------
4 1 2 3 4 5 6
-------------倒叙元素------------
6 5 4 3 2 1 4
-------------排序元素------------
1 2 3 4 4 5 6
5、Dictionary类
在C#中,Dictionary提供快速的基于键值的元素查找。它的语法结构如下:
Dictionary<[key], [value]>
当用户有很多元素的时候可以使用它。它包含在System.Collections.Generic命名空间中。在使用前,必须声明它的键类型的值类型。
注意:
(1)从一组键到一组值的映射,每一个添加项都是由一个值及其相关联的键组成。
(2)任何键都必须是唯一的。
(3)键不能为空引用null,若值为引用类型,则可以为空值。
(4)Key和Value可以是任何类型(string, int, class等)。
1、Dictionary类的方法和属性
名称 | 说明 |
Comparer | 获取用于确定字典中的键是否相等的IEqualityComparer<T> |
Count | 获取包含在Dictionary <TKey, TValue>中的键/值对的数目 |
Item | 获取或设置与指定的键相关联的值 |
Keys | 获取包含Dictionary<TKey, TValue>中的键的集合 |
Values | 获取包含Dictionary<TKey, TValue>中的值的集合 |
名称 | 说明 |
Add | 将指定的键和值添加到字典中 |
Clear | 从Dictionary<TKey, TValue>中移除所有的键和值 |
ContainsKey | 确定Dictionary<TKey, TValue>是否包含指定的键 |
ContainsValue | 确定Dictionary<TKey, TValue>是否包含指定值 |
GetEnumerator | 返回循环访问Dictionary<TKey, Tvalue>的枚举器 |
GetType | 获取当前实例的Type |
Remove | 从Dictionary<TKey, Tvalue>中移除所指定的键的值 |
ToString | 返回表示当前对象的字符串 |
TyGetValue | 获取与指定的键相关联的值 |
2、Dictionary类的用法
编写程序,通过使用Dictionary类的键值对,对数据元素进行遍历、查找和移除的操作。
using System;
using System.Collections.Generic;
namespace Project14
{
class Program
{
static void Main()
{
//实例化对象
Dictionary<int, string> dc = new Dictionary<int, string>();
//为集合添加元素
dc.Add(1, "C#");
dc.Add(2, "C++");
dc.Add(3, "ASP.NET");
dc.Add(4, "MVC");
Console.WriteLine("-----KeyValuePair遍历元素-----");
foreach (KeyValuePair<int, string> kvp in dc)
{
Console.WriteLine("Key = {0}; Value = {1}", kvp.Key, kvp.Value);
}
Console.WriteLine("--------通过Key查找元素-------");
if (dc.ContainsKey(1))
{
Console.WriteLine("Key:{0},Value:{1}", "1", dc[1]);
}
Console.WriteLine("--------仅遍历键Keys属性------");
Dictionary<int, string>.KeyCollection keyCol = dc.Keys;
foreach (int key in keyCol)
{
Console.WriteLine("Key = {0}", key);
}
Console.WriteLine("-------仅遍历键Valus属性------");
Dictionary<int, string>.ValueCollection valueCol = dc.Values;
foreach (string value in valueCol)
{
Console.WriteLine("Value = {0}", value);
}
Console.WriteLine("-------Remove方法移除元素-----");
dc.Remove(1);
if (dc.ContainsKey(1))
{
Console.WriteLine("Key:{0},Value:{1}", "1", dc[1]);
}
else
{
Console.WriteLine("不存在 Key : 1");
}
}
}
}
运行结果:
-----KeyValuePair遍历元素-----
Key = 1; Value = C#
Key = 2; Value = C++
Key = 3; Value = ASP.NET
Key = 4; Value = MVC
--------通过Key查找元素-------
Key:1,Value:C#
--------仅遍历键Keys属性------
Key = 1
Key = 2
Key = 3
Key = 4
-------仅遍历键Valus属性------
Value = C#
Value = C++
Value = ASP.NET
Value = MVC
-------Remove方法移除元素-----
不存在 Key : 1
四、泛型接口
为泛型集合类或表达集合中的项的泛型类定义接口通常很有用处。为避免对值类型的装箱或取消装箱操作,泛型类的首选项使用泛型接口。
在.NET Framework类库中定义了多个泛型接口,以将其用于System.Collections.Generic命名空间中的集合类。
1、泛型接口的声明
泛型接口的声明如下:
interface [接口名]<T>
{
[接口体]
}
声明泛型接口时,与声明一般接口的区别是增加了一个“<T>”。一般来说,声明泛型接口与声明非泛型接口遵循相同规则 。
2、常用的泛型接口
(1)Collection<T>接口由集合类实现,继承于非泛型接口IEnumerable。通过Collection<T>可以把实现Collection<T>的对象传送给需要将IEnumerable对象作为参数的方法。
(2)List<T>接口和Collection<T>接口一样,也是继承于非泛型接口IEnumerable。List<T>接口允许使用索引符访问集合,用户还可以在集合的任意位置插入或删除集合中的元素。
(3)IEnumerable<T>接口支持在指定类型的集合上,进行简单迭代。它定义了GetEnumerator方法,返回一个实现IEnumerable<T>的枚举,如果对集合使用foreach语句,那么就需要用到这个接口。
(4)IEnumerators<T>接口,此接口继承了非泛型接口IEnumerators和IDisposable。该接口支持在指定类型的集合上进行简单迭代,foreach语句的使用实现了此接口的枚举访问集合中的所有元素。
(5)Dictionary<TKey, Tvalue>接口是由元素的一个键和一个值的集合实现的。
(6)Comparer<T>接口是为了比较两个对象而实现的方法,使用Compare方法给集合中的元素排序。
(7)IEqualityComparer<T>接口是比较对象的第二个接口,可以对对象进行相等比较。它的Equals方法用于比较两对象是否相等,如相等就返回true,否则返回false。它的GetHashCode方法为每个对象返回一个唯一的值。
五、泛型方法
在有些情况下,一个类型中可能只有少数的方法成员用到了类型参数,这时没有必要将整个类型都定义成为泛型类。因此,就引入 了泛型方法。
在C#的泛型机制中,只支持在方法声明上包含类型参数的方法称为泛型方法。泛型方法可以在泛型类型中使用,也可以在非泛型类型中使用。
泛型方法的声明格式如下:
[修饰符] void [方法名] <类型参数T>
{
[方法体]
}
泛型方法与普通方法类似,只是在声明中包括类型参数T的方法。
注意:泛型方法定义的类型参数即可以作为方法的参数类型和返回类型,在foreach语句中也可以用来在方法的执行代码中定义局部变量。
编写程序,调用泛型方法。
using System;
namespace Project15
{
//定义普通类
public class MyClass
{
public bool Contains<T>(T[] TArry, T TValue)
{
foreach (T t in TArry)
{
//判断是否存在Tvalue
if (t.Equals(TValue))
{
return true;
}
}
return false;
}
}
class Program
{
static void Main(string[] args)
{
//定义int类型的数组,并初始化
int[] myint = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//由于MyClass是一个非静态的类,所以需要进行实例化
MyClass mc = new MyClass();
//调用泛型方法
bool mybool;
int testInt = 20;
//完整调用
mybool = mc.Contains<int>(myint, testInt);
//简写调用
// mybool = mc.Contains(myint, testInt);
if(mybool)
Console.WriteLine("数组中存在元素"+testInt);
else
Console.WriteLine("数组中不存在元素"+testInt);
}
}
}