泛型的由来:
没有泛型的时候, 当某个数据结构要保存未确定类型的数据,通常我们通过指定所有类型的根Object作为指定数据类型来实现对不同类型的兼容性.示例如下:
public class Stack
{
object[] items;
int count;
public void Push(object item) {...}
public object Pop() {...}
}
Stack中,有可能保存的是string,也许是int…..我们使用Object使得该类具有很好的兼容性,但它有不少缺点:
1,当我们取出保存的元素时,需要进行显示转换成适当的类型才能访问类型相关的特性,这让我们很难受….想想我们的H~~~~Helper.Collection
Stack stack = new Stack();
stack.Push(new Customer());
Customer c = (Customer)stack.Pop();
2,类型转换带来运行时类型检查的额外开销.(类型检查和动态类型分配)
3,如果我们要往里面保存值类型,就会导致装箱操作的发生,取出数据时的转换又导致拆箱操作,对性能的影响非常大
示例:E:\ETS\NetNew\BoxingInGenerics
4,无法控制事实存储的类型,如果我们用一个集合,希望它保存一系列的字符串.但程序中可能错误地存入了一个int类型的变量,程序无法在编译时发现该问题.
H2000Helper.Collection一样有这个问题,经常有人把一个TextBox扔进去
5,有可能被错误地转换,而导致运行时问题,而不能在编译时发现.以下程序编译是没有问题的:
Stack stack = new Stack();
stack.Push(new Customer());
string s = (string)stack.Pop();
泛型的出现,解决了这些问题
泛型类使用示例
Stack<int> stack = new Stack<int>();
stack.Push(3);
int x = stack.Pop();
特点:1,定义和构造与普通类不同都有 <int> 这个特殊部分,叫构造类型,代表该泛型实例所容纳的数据类型
其实构造类型是对类定义的一个占位符号,本身是一个不完整的类定义,看以下代码有没有问题.
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Stack st;
Console.WriteLine(“Hello World!”);
}
}
}
Stack st 应该 Stack<string> st; Stack<string> 才是一个完整的类.
当我们使用Stack<string>类时,string 将替换所有的占位符T
由于泛型的构造类型可能为任意类型,所以,我们如果不仅仅用泛型类储存数据,则需要对实例进行显式转换.
public class Dictionary<K,V>
{
public void Add(K key, V value)
{
...
if (((IComparable)key).CompareTo(x) < 0) {...}//此处会进行类型检查,性能开销
...
}
}
如果添加进来的类型是不兼容IComparable的,则会导致运行时错误!!但是
我们还有办法,微软考虑到了这一点,我们可以限制构造类型
public class Dictionary<K,V> where K: IComparable
{
…….
}
同时还解决了运行时类型检查带来的性能损失
public class Dictionary<K,V> where K: IComparable
{
public void Add(K key, V value)
{
...
if (key.CompareTo(x) < 0) {...}//直接就是IComparable,无需显示转换
...
}
}
泛型一样适用与方法,示例如下:
static void Test<T>(T param) where T :IDisposable
{
param.Dispose();
}
QUIZ:1,以下代码有问题吗?
class TestGen<T> where T:IComparable
{
T myVar;
public TestGen()
{
myVar = new T();
}
}
由于无法确定T的构造函数,所以无法new
QUIZ:2,
接口支持泛型吗?
委派呢?
支持!
public delegate void TestDelegate<T>(T input);
Interface ITestGen<T>
{}
如果你耐心看到这里,我想,对泛型,你该已经了解了...