泛型编程
class GenericStatc<T> //T:类型参数,当然名字可以不必是T
{
T[] store; //此处使用类型参数
int index;
public GenericStatc(int size)
{
this.store = new T[size];
this.index = 0;
}
public void Push(T x)
{
store[index++] = x; //stre[index] = x;index++;
}
public T Pop() //T用为返回类型
{
return store[--index];
}
}
C#泛型定义
1、通过参数化类型来达到类型的抽象化,从面得到更好的面向对象体验,C#泛型相对C++提供更强的类型安全。
2、实例化泛型类:
GenericStatc<string> strGStaic = new GenericStatc<string>(3);
C#泛型的底层机制
C#泛型代码在编译成IL代码和元数据时会是一个特殊的占位符,而只有在JIT运行时编译时才会实例化泛型类型,不象Java只是在编译时把代码编译为object
第一轮编译,编译器只为GenericStack<T>生成泛型板的IL代码和元数据,并不进行泛型类型的实例化,T在中间只是占位符
JIT编译时当JIT编译器第一次见到GenericStack<string>就会用string替换T---泛型的实例化
CLR为所有的引用类型产生同一份代码,而为值类型产生各自独立的代码,而java的假泛型会把值类型也转为object
C#泛型的特点
C#的泛型采用“基类,接口,构造器,值类型/引用类型”四种约束来对类型参数的“显示约束”。
C#泛型语法
C#可单独声明泛型类型或结构,也可以在基类中使用泛型类型的声明.
如果基类是泛型类型,它的类型参数要么已经实例化,要么由子类负责实例化
class C<A,B>{} //合法,单独声明泛型类型
class D:C<string,int>{} //合法,基类是泛型类型,它的类型参数已经实例化
class E<A,B>:C<A,B>{} //合法,基类是泛型类型,由子类负责实例化
class F<A,B>:C<string,int>{} //合法,基类是泛型类型,它的类型参数已经实例化
class G:C<A,B>{} //不合法,因为C<A,B>{}是一个引用类型,没有实例化,子类也没实例化基类的类型参数
泛型接口
泛型接口的类型参数要么已经实例化要么来源于实现接口的类
interface IList<T>
{
T[] GetElements();
}
interface IDictionary<A, B>
{
void Add(A key, B value);
}
class List<T> : IList<T>,IDictionary<int,T>
{
public T[] GetElements()
{
return null;
}
public void Add(int key, T value)
{
}
}
泛型方法
1、可以在方法声明上包含类型参数
2、泛型不支持在方法外的其它成员(属性,事件,索引器,构造函数,析构函数)的声明上包含类型参数,但这些成员本身可以包含在泛型类型中,并使用泛型类型的类型参数
3、泛型方法可以包含在非泛型类型中
public class Finder
{
public static int Find<T>(T[] items, T item)
{
for (int i = 0; i < items.Length; i++)
{
if (item.Equals(items[i]))
{
return i;
}
}
return -1;
}
}
static void Main(string[] args)
{
int index = Finder.Find<string>(new string[] { "aa", "bb", "cc" }, "bb");
Console.WriteLine(index);
}
泛型方法的重载
class Traffic
{
//不能构成重载,因为两个类型不确定,有可能在传参时,类型一样,所有不能构成重载
void F1<T>(T[] a, int i)
{ }
void F1<U>(U[] a, int i)
{ }
//可以构成重载
void F2<T>(int x) { }
void F2<T>(string x) { }
//不能构成重载,自动报错了
void F3<T>(T t) where T:A{}
void F3<T>(T t) where T : B { }
}
泛型方法的重写
abstract class Base
{
public abstract T F<A, B>(A a, B b) where B : A;
public abstract T G<T>(A a) where T : IComparable;
}
public class Derive : Base
{
public override X F<A, B>(A a, B b) //合法,约束被默认继承
{
throw new NotImplementedException();
}
}
泛型约束
1、C#泛型要求对所有泛型类型或泛型方法的类型参数的任何假定,都要基于”显示的约束”,目的是维护.net所强调的的类型安全
2、约束由where子句表达,有基类,接口,构造器,值类型/引用类型四种约束
3、显示约束如果没有指定,泛型类型参数将只能访问Object类型中的公有方法
基类约束
class A { public void F1() { } }
class B { public void F2() { } }
class C<S, T>
where S : A,new()
where T : B
{
public void FF()
{
S s = new S();
s.F1();
}
}
接口约束