0x00 - c#自问自答 - 泛型
1. 什么是泛型(Generics)
C#泛型通过参数化类型
,实现同一份代码操作多个数据类型,实现了代码的复用。
C#编译器把代码编译为 IL代码时,采用特殊的占位符来表示类型,且有操作泛型的IL指令;当CLR真正运行代码时,JIT编译为真正的类型,即类型的晚绑定。
如果不使用泛型,对于不同的参数类型(int,double,single)可能都要重载(overloading)一遍,但使用泛型则减少了代码量,同时获得了强类型的支持。
泛型支持对参数类型进行约束,包括有一个主约束和多个次约束。有以下五种类型的约束:
- T:strcut,值类型
- T:class,引用类型
- T:new(),必须有public无参构造函数,同其他约束放在一起时,必须放在最后
- T:基类名,必须是基类或其子类
- T:接口名称,必须是接口或实现指定的接口
Generic classes and methods combine reusability
, type safety
and efficiency
in a way that their non-generic counterparts cannot. Generics are most frequently used with collections
and the methods operate on them.
Version 2.0 of the .NET Framework class library provides a new namespace, System.Collections.Generic
, which contains several new generic-based collection classes.
In most cases, you should use the List<T>
class provided by the .NET Framework class library instead of creating your own.
// type parameter T in angle brackets
public class GenericList<T>
{
// The nested class is also generic on T.
private class Node
{
// T used in non-generic constructor.
public Node(T t)
{
Next = null;
Data = t;
}
public Node Next{get;set;}
public T Data {get; set;}
}
private Node head;
public GenericList()
{
head = null;
}
//向前添加
public void AddHead(T t)
{
Node n = new Node(t);
n.Next = head;
head = n;
}
//支持遍历
public IEnumerator<T> GetEnumerator()
{
Node current = head;
while (current != null)
{
yield return current.Data;
current = current.Next;
}
}
}
class TestGenericList
{
public static void Main()
{
// int is the type argument
GenericList<int> list = new GenericList<int>();
for (int x = 0; x < 10; x++)
{
list.AddHead(x);
}
foreach (int i in list)
{
System.Console.Write(i + " ");
}
System.Console.WriteLine("\nDone");
}
}
//out : 9 8 7 6 5 4 3 2 1 0
//out : Done
2. 泛型之前,ArrayList有什么缺点?
ArrayList dynamically resizes, it grows in capacity as elements are added(if space is needed).
当容量不足时,ArrayList会自动增加容量。
ArrayList.AddRange() 方法使用了 Array.Copy() 方法,性能要比for循环好一些。
ArrayList.Add( object value)
,可以添加各种类型。
所以用下标访问一个元素时,得到的是object
,使用前要进行类型转换。
class Program
{
static void Main()
{
//
// Create an ArrayList with three strings.
//
ArrayList list = new ArrayList();
list.Add("man");
list.Add("woman");
list.Add("plant");
//
// Loop over ArrayList.
//
for (int i = 0; i < list.Count; i++)
{
string value = list[i] as string;//类型转换
Console.WriteLine(value);
}
}
}
List versus ArrayList (List vs ArrayList)(泛型 vs 非泛型)
List 比 ArrayList不仅仅避免了 boxing and unboxing , 同时在代码编写时就可以检测类型匹配,减少代码错误。
List.BinarySearch() 只有在List已经排序过才能正常工作。
ArrayList is a collection that is best avoided. But it is often used in older legacy programs—so it must be supported. Newer .NET Framework versions offer better collections.
Array vs ArrayList
Array 是一个存储相同元素类型的固定大小的顺序集合。
- ArrayList因为内部使用的是 object,所以可以存放各种类型,但会频繁装箱拆箱。
- ArrayList是容量大小动态变化,可以自动增长。
所以,性能排序: Array > List > ArrayList;避免使用ArrayList
3. 重载 vs 泛型
重载: 同一个方法名,不同的参数类型、个数、或顺序
泛型:一个方法通过类型参数化,可以操作多种数据类型