System.Collections: ArrayList类
var list = new ArrayList();
list.Add(44); //装箱操作
int i1 = (int)list[0]; //拆箱操作
foreach (int i2 in list)
{
Console.WriteLine(i2); //拆箱操作
}
装箱和拆箱操作很容易使用,但性能损失比较大,遍历许多项时尤其如此。
System.Collections.Generic: List<T>
List<类>不使用对象,而是在使用时定义类型,在下面的例子中,List<T>类的泛型类型定义为int,所以int类型在JIT编译器动态生成的类中使用,不再进行装箱和拆箱操作
var list = new List<int>();
list.Add(44);
int i1 = list[0];
foreach (int i2 in list)
{
Console.WriteLine(i2);
}
var list = new List<int>();
list.Add(44);
var stringList = new List<string>();
stringList.Add("mystring");
var myClassList = new List<myClass>();
myClassList.Add(new MyClass());
泛型类型可以在一种语言中定义,在任何其他.NET语言中使用。
public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
public delegate TOutput Converter<TInput, TOutput>(TInput from);
public class SortedList<TKey, TValue>();
public class LinkNodeList
{
/*
* 链表中,一个元素引用下一个元素
* Value:初始化构造函数
* Previous:上一个元素的引用
* Next:下一个元素的引用
*/
public LinkNodeList(object value)
{
this.Value = value;
}
public object Value { get; private set; }
public LinkNodeList Previous { get; internal set; }
public LinkNodeList Next { get; internal set; }
}
public class LinkedList
{
/*
* LinkeList类包含LinkedNodeList类型的两个属性Last,First;
* First: 链表的头
* Last: 链表的尾
* AddLast(): 在链表尾添加一个新元素
* GetEnumerator(): 通过其实现foreach遍历
*/
public LinkNodeList First { get; private set; }
public LinkNodeList Last { get; private set; }
public LinkNodeList AddLast(object node)
{
var newNode = new LinkNodeList(node);
if (First == null)
{
First = newNode;
Last = First;
}
else
{
LinkNodeList previous = Last;
Last.Next = newNode;
Last = newNode;
Last.Previous = previous;
}
return newNode;
}
public IEnumerator GetEnumerator()
{
LinkNodeList current = First;
while (current != null)
{
yield return current.Value;
current = current.Next;
}
}
}
使用LinkedList的示例:
class Program
{
static void Main(string[] args)
{
LinkedList testList = new LinkedList();
testList.AddLast(1);
testList.AddLast(2);
testList.AddLast(3);
foreach (int i in testList)
{
Console.WriteLine(i);
}
Console.ReadLine();
}
}
下面创建链表的泛型版本。泛型类的定义与一般类类似,只是要使用泛型类型声明。之后,泛型类型就可以在类中用作一个字段成员,或者方法的参数类型。
public class LinkNodeList<T>
{
public LinkNodeList(T value)
{
this.Value = value;
}
private T Value {get; private set;}
private LinkNodeList<T> Next {get; internal set;}
private LinkNodeList<T> Prev {get; internal set;}
}
下面的代码将LinkedList类也改为泛型类:
public class LinkedList<T>:IEnumerator<T>
{
public LinkNodeList<T> First {get; private set;}
public LinkNodeList<T> Last {get; private set;}
public LinkNodeList<T> AddLast(T node)
{
var newNode = new LinkNodeList<T>(node);
if (First == null)
{
First = newNode;
Last = First;
}
else
{
LinkNodeList<T> previous = Last;
Last.Next = newNode;
Last = newNode;
Last.Prev = previous;
}
public IEnumerator<T> GetEnumerator()
{
LinkNedeList<T> current = First;
while (current != null)
{
yield return current.Value;
current = current.Next;
}
}
}
}
//泛型文档管理器的示例
//先创建一个新的控制台项目DocumentManager, 并添加DocumentManager类。AddDocument()方法将一个文档添加到队列中。如果队列不为孔,IsDocumentAvailable只读属性就返回true
using System;
using System.Collections.Generics
{
namespace Wrox.ProCSharp.Generic
{
public class DocumentManager<T>
{
private readonly Queue<T> documentQuene = new Queue<T>;
public void AddDocument()
{
lock(this)
{
documentQueue.Enqueue(doc);
}
}
public bool IsDocumentAvailable
{
get { return documentQueue.Count > 0; }
}
}
}
}
当需要将类型T指定为null时,不能把null赋予泛型类型。原因是泛型类型也可以实例化为值类型,而null只能应用于引用类型。
在CSharp中,可以使用default关键字,将null赋予引用,将0赋予值类型
public T GetDocument()
{
T doc = default(T);
lock(this)
{
doc = documentQueue.Dequeue();
}
return doc;
}