泛型与非泛型集合类的区别及使用例程,包括ArrayList,Hashtable,List<T>,Dictionary<Tkey,Tvalue>,SortedList<Tkey,Tvalue>,Queue<T>,Stack<T>等
泛型与非泛型集合类在C#程序中是非常重要的一个基础概念,这里列一个表来进行对比:
|
非泛型集合类 |
泛型集合类 |
描述 |
|
ArrayList |
List<T> |
表示具有动态大小的对象数组 |
|
Hashtable |
Dictionary<Tkey,Tvalue> |
由键值对组成的集合 |
|
SortedList |
SortedList<Tkey,Tvalue> |
和字典相似但有排序功能的集合 |
|
Queue |
Queue<T> |
表示标准的先进先出(FIFO)队列 |
|
Stack |
Stack<T> |
后进先出(LIFO)队列,提供压入和弹出功能 |
泛型与非泛型集合类在概念和功能上各有不同,其中非泛型集合类在取出值时需要进行类型的转换操作,如果加入值类型会引起装箱和拆箱的操作,这会带来巨大的性能额外开销,如果掌握好泛型数组之后可以不再需要用非泛型的数组了,同时带来类型安全的好处并减少在值类型和引用类型之间的装箱和拆箱。
下面做一个例程来演示一下,
例程是顺手在WPF下做的,虽然不是C#winform,但差不多是一回事,界面代码就不贴了。
先做一个学生类:

public class student
{
public int Number { get; set; }
public string Name { get; set; }
public bool Sex { get; set; }
public student(int _number, string _name, bool _sex)
{
Number = _number;
Name = _name;
Sex = _sex;
}
public override string ToString()
{
return string.Format("序号:{0},姓名:{1},性别:{2}",
Number.ToString(), Name, Sex ? "男" : "女");
}
}

一、ArrayList与List<T>示例

ArrayList arrayStudents = new ArrayList();
List<student> listStudnets = new List<student>(); private void Button_Click(object sender, RoutedEventArgs e)
{
addData0();
showExemple0();
} private void addData0()
{
arrayStudents.Add(new student(1, "小颗豆一", true));
arrayStudents.Add(new student(3, "小颗豆二", false));
arrayStudents.Add(new student(5, "小颗豆三", true));
arrayStudents.Add(new student(2, "小颗豆四", false));
arrayStudents.Add(new student(4, "小颗豆五", true));
arrayStudents.Add(new student(6, "小颗豆六", false));
arrayStudents.Add("这里冒一个字符串,需要转换,如果这里是值类型还要进行装箱与拆箱,带来额外的开销!"); listStudnets.Add(new student(1, "小颗豆一", true));
listStudnets.Add(new student(3, "小颗豆二", false));
listStudnets.Add(new student(5, "小颗豆三", true));
listStudnets.Add(new student(2, "小颗豆四", false));
listStudnets.Add(new student(4, "小颗豆五", true));
listStudnets.Add(new student(6, "小颗豆六", false));
} private void showExemple0()
{
richTextBox1.AppendText("--------ArrayList与List<T>示例--------\r\n");
richTextBox1.AppendText("--------非泛型数组的操作(需要强制转换)--------\r\n");
foreach (var item in arrayStudents)
{
if (item is student)
richTextBox1.AppendText(item.ToString() + "\r\n");
else
richTextBox1.AppendText((string)item + "\r\n");
}
richTextBox1.AppendText("--------泛型数组的操作(不需要强制转换)--------\r\n");
foreach (var item in listStudnets)
{
richTextBox1.AppendText(item.ToString() + "\r\n");
}
}

注意观察代码中ArrayList接收的值包括类和字符串,所以要有不同的强制转换,虽然正常运行,但这样带来了安全隐患,泛型集合不需要转换可以轻松调用学生类中自定义的.ToString(),运行效果如下图:

二、Hashtable与Dictionary<Tkey,Tvalue>示例

private void button1_Click(object sender, RoutedEventArgs e)
{
richTextBox1.Document.Blocks.Clear();
addData1();
showExemple1();
} Hashtable hashSudents = new Hashtable();
Dictionary<string ,student> DictStudents = new Dictionary<string ,student>(); private void addData1()
{
hashSudents.Add("序号1", new student(1, "小颗豆一", true));
hashSudents.Add("序号2", new student(3, "小颗豆二", false));
hashSudents.Add("序号3", new student(5, "小颗豆三", true));
hashSudents.Add("序号4", new student(2, "小颗豆四", false));
hashSudents.Add("序号5", new student(4, "小颗豆五", true));
hashSudents.Add("序号6", new student(6, "小颗豆六", false)); DictStudents.Add("序号1", new student(1, "小颗豆一", true));
DictStudents.Add("序号2", new student(3, "小颗豆二", false));
DictStudents.Add("序号3", new student(5, "小颗豆三", true));
DictStudents.Add("序号4", new student(2, "小颗豆四", false));
DictStudents.Add("序号5", new student(4, "小颗豆五", true));
DictStudents.Add("序号6", new student(6, "小颗豆六", false));
}
private void showExemple1()
{
richTextBox1.AppendText("--------Hashtable与Dictionary<Tkey,Tvalue>示例--------\r\n");
richTextBox1.AppendText("--------非泛型数组的操作(需要强制转换),注意顺序是特定的------\r\n");
foreach (DictionaryEntry item in hashSudents)
{
richTextBox1.AppendText(item.Key.ToString() + ((student)item.Value).ToString() + "\r\n");
}
richTextBox1.AppendText("包含序号2=" + hashSudents.ContainsKey("序号2").ToString() + "\r\n");
richTextBox1.AppendText("包含序号9=" + hashSudents.ContainsKey("序号9").ToString() + "\r\n"); richTextBox1.AppendText("--------泛型数组的操作(不需要强制转换),顺序是原来的顺序-----\r\n");
foreach (KeyValuePair<string, student> item in DictStudents)
{
richTextBox1.AppendText(item.Key.ToString() + item.Value.ToString() + "\r\n");
}
richTextBox1.AppendText("包含序号2=" + DictStudents.ContainsKey("序号2").ToString() + "\r\n");
richTextBox1.AppendText("包含序号9=" + DictStudents.ContainsKey("序号9").ToString() + "\r\n");
}

注意,1)Hashtable不仅需要强制转换,由于它内部的特殊性,所得到的结果跟原序中的结果顺序是不一致的,在需要排序的时候会很麻烦,但Dictionary<Tkey,Tvalue>不仅不需要强制转换,而且顺序跟原序是一致的。
2)Hashtable和Dictionary<Tkey,Tvalue>都仍具有.ContainsKey("序号2");(检查是否包含某键值的项)的方法效率很高。
运行效果如图:

三、SortedList与SortedList<Tkey,Tvalue>示例

SortedList sortListStudents = new SortedList();
SortedList<int, student> sortStudents = new SortedList<int, student>(); private void button2_Click(object sender, RoutedEventArgs e)
{
richTextBox1.Document.Blocks.Clear();
addData2();
showExemple2();
}
private void addData2()
{
sortListStudents.Add(50, new student(1, "小颗豆一", true));
sortListStudents.Add(20, new student(3, "小颗豆二", false));
sortListStudents.Add(80, new student(5, "小颗豆三", true));
sortListStudents.Add(65, new student(2, "小颗豆四", false));
sortListStudents.Add(44, new student(4, "小颗豆五", true));
sortListStudents.Add(99, new student(6, "小颗豆六", false)); sortStudents.Add(50, new student(1, "小颗豆一", true));
sortStudents.Add(20, new student(3, "小颗豆二", false));
sortStudents.Add(80, new student(5, "小颗豆三", true));
sortStudents.Add(65, new student(2, "小颗豆四", false));
sortStudents.Add(44, new student(4, "小颗豆五", true));
sortStudents.Add(99, new student(6, "小颗豆六", false));
}
private void showExemple2()
{
richTextBox1.AppendText("--------SortedList与SortedList<Tkey,Tvalue>示例--------\r\n");
richTextBox1.AppendText("--------非泛型数组的操作(需要强制转换)---------\r\n");
foreach (DictionaryEntry item in sortListStudents )
{
richTextBox1.AppendText(item.Key.ToString() + ((student)item.Value).ToString() + "\r\n");
}
richTextBox1.AppendText("--------泛型数组的操作(不需要强制转换)--------\r\n");
foreach (KeyValuePair <int,student > item in sortStudents )
{
richTextBox1.AppendText(item.Key.ToString() + item.Value.ToString() + "\r\n");
}
}

在这个例程中,两个集合类工作都很好的实现了排序功能,差别仍是一个有强制转换,一个不需要。运行效果如图:

四、Queue与Queue<T>示例(先进先出)

Queue queueStuds = new Queue();
Queue <student > queueStudents=new Queue<student> ();//先进先出
private void button3_Click(object sender, RoutedEventArgs e)
{
richTextBox1.Document.Blocks.Clear();
addData3();
showExemple3();
} private void addData3()
{
queueStuds.Enqueue(new student(1, "小颗豆一", true));
queueStuds.Enqueue(new student(3, "小颗豆二", false));
queueStuds.Enqueue(new student(5, "小颗豆三", true));
queueStuds.Enqueue(new student(2, "小颗豆四", false));
queueStuds.Enqueue(new student(4, "小颗豆五", true));
queueStuds.Enqueue(new student(6, "小颗豆六", false)); queueStudents.Enqueue(new student(1, "小颗豆一", true));
queueStudents.Enqueue(new student(3, "小颗豆二", false));
queueStudents.Enqueue(new student(5, "小颗豆三", true));
queueStudents.Enqueue(new student(2, "小颗豆四", false));
queueStudents.Enqueue(new student(4, "小颗豆五", true));
queueStudents.Enqueue(new student(6, "小颗豆六", false));
}
private void showExemple3()
{
richTextBox1.AppendText("--------Queue与Queue<T>示例(先进先出)--------\r\n");
richTextBox1.AppendText("--------非泛型数组的操作(需要强制转换)---------\r\n");
while (queueStuds .Count >0)
{
richTextBox1.AppendText(((student)queueStuds.Dequeue()).ToString() + "\r\n");
}
richTextBox1.AppendText("现在数组个数="+queueStuds.Count.ToString() + "\r\n"); richTextBox1.AppendText("--------泛型数组的操作(不需要强制转换)(先进先出)---------\r\n");
while (queueStudents.Count > 0)
{
richTextBox1.AppendText(queueStudents.Dequeue().ToString() + "\r\n");
}
richTextBox1.AppendText("现在数组个数=" + queueStudents.Count.ToString() + "\r\n");
}

Queue与Queue<T>都使用Enqueue()方法将一个对象加入到队列中,按照先进先出的法则,入栈后使用Dequeue()方法出队。出队后该成员被移除,区别仍是强制转换的问题。运行效果如图:

五、Stack与Stack<T>示例(先进后出,注意显示数据的顺序)

Stack stackStudnets1 = new Stack();
Stack<student> stackStudents2 = new Stack<student>();
private void button4_Click(object sender, RoutedEventArgs e)
{
richTextBox1.Document.Blocks.Clear();
addData4();
showExemple4();
}
private void addData4()
{
stackStudnets1.Push(new student(1, "小颗豆一", true));
stackStudnets1.Push(new student(3, "小颗豆二", false));
stackStudnets1.Push(new student(5, "小颗豆三", true));
stackStudnets1.Push(new student(2, "小颗豆四", false));
stackStudnets1.Push(new student(4, "小颗豆五", true));
stackStudnets1.Push(new student(6, "小颗豆六", false)); stackStudents2.Push(new student(1, "小颗豆一", true));
stackStudents2.Push(new student(3, "小颗豆二", false));
stackStudents2.Push(new student(5, "小颗豆三", true));
stackStudents2.Push(new student(2, "小颗豆四", false));
stackStudents2.Push(new student(4, "小颗豆五", true));
stackStudents2.Push(new student(6, "小颗豆六", false));
}
private void showExemple4()
{
richTextBox1.AppendText("--------Stack与Stack<T>示例(先进后出,注意显示数据的顺序)--------\r\n");
richTextBox1.AppendText("--------非泛型数组的操作(需要强制转换)---------\r\n");
for (int i = 0; i < stackStudnets1 .Count ; i++)
{
richTextBox1.AppendText(((student)stackStudnets1.Peek ()).ToString() + "\r\n");
}
richTextBox1.AppendText("(Stack.Peek()是返回不移除)现在数组个数=" + stackStudnets1.Count.ToString() + "\r\n");
richTextBox1.AppendText("注意:以上数据次次返回的都是最后一次加到数组中的数----------" + "\r\n");
richTextBox1.AppendText("下边:看看用Stack.Pop()返回并移除的结果:" + "\r\n");
while (stackStudnets1.Count > 0)
{
richTextBox1.AppendText(((student)stackStudnets1.Pop()).ToString() + "\r\n");
}
richTextBox1.AppendText("(Stack..Pop()是返回并移除)现在数组个数=" + stackStudnets1.Count.ToString() + "\r\n"); richTextBox1.AppendText("--------泛型数组的操作(不需要强制转换)---------\r\n");
while (stackStudents2.Count > 0)
{
richTextBox1 .AppendText ((stackStudents2 .Pop ().ToString ()+"\r\n"));
}
richTextBox1.AppendText("(Stack.Pop()是返回并移除)现在数组个数=" + stackStudents2.Count.ToString() + "\r\n"); }

这个集合类,本人感觉用在撤销操作是最方便不过的了,专门记录用户的操作,当需要撤销时,后进的是先出,对象所在位置都不需要判断,如果是泛型直接用即可,如果是非泛型转换一下。
注意,第一部分全是最后一次加入的成员,因为用的是Peek ()方法:返回不移除成员,永远返回最后一个加入的成员;如果用.Pop()方法就不同了:返回并移除,显示的效果及顺序如下图:

泛型与非泛型集合类的区别及使用例程,包括ArrayList,Hashtable,List<T>,Dictionary<Tkey,Tvalue>,SortedList<Tkey,Tvalue>,Queue<T>,Stack<T>等的更多相关文章
- .NET泛型与非泛型的问题
泛型集合通常情况下,建议您使用泛型集合,因为这样可以获得类型安全的直接优点而不需要从基集合类型派生并实现类型特定的成员.下面的泛型类型对应于现有的集合类型:1.List 是对应于 ArrayList ...
- C# 通过IEnumberable接口和IEnumerator接口实现泛型和非泛型自定义集合类型foreach功能
IEnumerator和IEnumerable的作用 其实IEnumerator和IEnumerable的作用很简单,就是让除数组和集合之外的类型也能支持foreach循环,至于foreach循环,如 ...
- C#非泛型集合类与泛型集合类的区别 (转)
来自:http://blog.csdn.net/jiayanhui2877/article/details/7623845 C# 泛型集合之非泛型集合类与泛型集合类的对应: ArrayList对应Li ...
- C#非泛型集合和泛型集合的超级详解
C# 泛型集合之非泛型集合类与泛型集合类的对应: ArrayList对应List HashTable对应Dictionary Queue对应Queue Stack对应Stack SortedList对 ...
- 编写高质量代码改善C#程序的157个建议——建议20:使用泛型集合代替非泛型集合
建议20:使用泛型集合代替非泛型集合 在建议1中我们知道,如果要让代码高效运行,应该尽量避免装箱和拆箱,以及尽量减少转型.很遗憾,在微软提供给我们的第一代集合类型中没有做到这一点,下面我们看Array ...
- C#非泛型集合和泛型集合
第一 : ArrayList(非泛型集合) 与List(泛型集合) ArrayList 是数组的复杂版本.ArrayList 类提供在大多数 Collections 类中提供但不在 Array(数 ...
- Linq操作非泛型集合
我们都知道,Linq能查询泛型集合,确切的说是:LINQ能实现查询泛型对象或者实现了IEnumerable.但是,很遗憾的是诸如ArrayList这样的非泛型集合并没有实现IEnumerable.那咋 ...
- Linq查询非泛型集合要指定Student类型(比如List)
#region Linq to 集合查询非泛型集合要指定Student类型 //ArrayList list = new ArrayList(); //li ...
- DataTable数据集转换为List非泛型以及泛型方式
前言 DataTable是断开式的数据集合,所以一旦从数据库获取,就会在内存中创建一个数据的副本,以便使用.由于在实际项目中,经常会将DataTable中的每行数据转换为Model,然后放到List集 ...
随机推荐
- MySQL另类的备份恢复方法——innodb可传输表空间
Preface There're many ways in backing up or migrating data from one server to another one.Lo ...
- webkit几种内核版本的优劣对比总结
01.Open-Webkit-Sharp 默认不存在JS对话框,如果需要显示alert box,则需要在ShowJavaScriptAlertPanel进行捕捉,然后显示对话框: 02.Open-We ...
- CodeMirror的使用方法
最近项目中用到了CodeMirror这个代码编辑器,感觉非常好用,可以设置很多种代码格式.默认前提是你已经正确引入了所有的js文件和css文件. 下面是我在项目中用到过和在网上搜集整理的使用方法: 1 ...
- jquery 改变标签可见状态的几种方式
第一种: $(selector).show(); //立即显示指定标签 $(selector).hide();//立即隐藏指定标签 第二种: $(selector).fadeIn(ms);//在指定毫 ...
- 在唯一密钥属性“fileExtension”设置为“.”时,无法添加类型为“mimeMap”的重复集合项
在ASP.NET 网站的配置文件中添加了MIME类型,但是运行网站后在IIS上和页面上提示"在唯一密钥属性“fileExtension”设置为“.woff”时,无法添加类型为“mimeMap ...
- SSO 单点登录总结(PHP)
本篇文章根据个人理解的知识整理汇总,如有不足之处,请大家多多指正. 单点登录(SSO--Single Sign On)的应用是很普遍的,尤其在大型网站系统中,比如百度,登录百度账号和,再转到百度经验. ...
- list函数及list对象的reverse方法
list的reverse方法,是就地reverse,不返回值 如a是一个list,a.reverse()直接将a这个list给reverse了,所以如果print(a.reverse())就是None ...
- 大话CNN经典模型:VGGNet
2014年,牛津大学计算机视觉组(Visual Geometry Group)和Google DeepMind公司的研究员一起研发出了新的深度卷积神经网络:VGGNet,并取得了ILSVRC20 ...
- Java线程和多线程(七)——ThreadLocal
Java中的ThreadLocal是用来创建线程本地变量用的.我们都知道,访问某个对象的所有线程都是能够共享对象的状态的,所以这个对象状态就不是线程安全的.开发者可以通过使用同步来保证线程安全,但是如 ...
- MySQL单表查询语句练习题
/*1. 查询出部门编号为30的所有员工*/ /* 分析: 1). 列:没有说明要查询的列,所以查询所有列 2). 表:只一张表,emp 3). 条件:部门编号为30,即deptno=30 */ ; ...