C#2.0泛型学习
C#的泛型能力有CLR在运行时支持,它既不同于C++在编译时所支持的静态模板,也不同于Java在编译器层面使用“搽拭法”支持的简单的泛型。
C#的泛型支持包括类、结构、接口、委托共四种泛型类型,以及方法成员。
C#的泛型采用“基类,接口,构造器,值类型/引用类型”的结束方式来实现对类型参数的“显示约束”,它不支持C++模板那样的基于签名的隐式约束。
C#的泛型支持包括类、结构、接口、委托共四种泛型类型,以及方法成员。
C#的泛型采用“基类,接口,构造器,值类型/引用类型”的结束方式来实现对类型参数的“显示约束”,它不支持C++模板那样的基于签名的隐式约束。
//C#泛型演示
class Stack<T>
{
private T[] store;
private int size;
public Stack()
{
store = new T[10];
size = 0;
}
public void Push(T x)
{
store[size++] = x;
}
public T Pop()
{
return store[--size];
}
}
所谓泛型,即通过参数化类型来实现在同一份代码上操作多种数据类型。泛型编程是一种编程范式,它利用“参数化类型”将类型抽象化,从而实现更为灵活的运用。
class Stack<T>
{
private T[] store;
private int size;
public Stack()
{
store = new T[10];
size = 0;
}
public void Push(T x)
{
store[size++] = x;
}
public T Pop()
{
return store[--size];
}
}
所谓泛型,即通过参数化类型来实现在同一份代码上操作多种数据类型。泛型编程是一种编程范式,它利用“参数化类型”将类型抽象化,从而实现更为灵活的运用。
//泛型类与结构
class C<U, V> { } //合法
class D : C<string, int> { } //合法
class E<U, V> : C<U, V> { } //合法
class F<U, V> : C<string, int> { } //合法
class G : C<U, V> { } //非法
C#除可单独声明泛型类型(包括类与结构)外,也可在基类中包含泛型类型的声明。但基类如果是泛型类,它的类型参数要么实例化,要么来自于子类(同样是泛型类型)声明的类型参数。
class C<U, V> { } //合法
class D : C<string, int> { } //合法
class E<U, V> : C<U, V> { } //合法
class F<U, V> : C<string, int> { } //合法
class G : C<U, V> { } //非法
C#除可单独声明泛型类型(包括类与结构)外,也可在基类中包含泛型类型的声明。但基类如果是泛型类,它的类型参数要么实例化,要么来自于子类(同样是泛型类型)声明的类型参数。
//泛型类型的成员
class C<V>
{
public V f1; //声明字段
public D<V> f2; //作为其他泛型类型的参数
public C(V x)
{
this.f1 = x;
}
}
泛型类型的成员可以使用泛型类型声明中的类型参数。但类型参数如果没有任何约束,则只能在该类型上使用System.Object集成的公有成员。
class C<V>
{
public V f1; //声明字段
public D<V> f2; //作为其他泛型类型的参数
public C(V x)
{
this.f1 = x;
}
}
泛型类型的成员可以使用泛型类型声明中的类型参数。但类型参数如果没有任何约束,则只能在该类型上使用System.Object集成的公有成员。
//泛型接口
interface IList<T>
{
T[] GetElements();
}
interface IDictionary<K, V>
{
void Add(K key, V value);
}
//泛型接口的类型参数要么已经实例化,
//要么来源于实现类声明的类型参数
class List<T> : IList<T>, IDictionary<int, T>
{
public T[] GetElements() { return null; }
public void Add(int index, T value) { }
}
interface IList<T>
{
T[] GetElements();
}
interface IDictionary<K, V>
{
void Add(K key, V value);
}
//泛型接口的类型参数要么已经实例化,
//要么来源于实现类声明的类型参数
class List<T> : IList<T>, IDictionary<int, T>
{
public T[] GetElements() { return null; }
public void Add(int index, T value) { }
}
//泛型委托
delegate bool Predicate<T>(T value);
class X
{
static bool F(int i) { }
static bool G(string s) { }
static void Main(string[] args)
{
Predicate<string> p2 = G;
Predicate<int> p1 = new Predicate<int>(F);
}
}
泛型委托支持在委托返回值和参数上应用参数类型,这些参数类型同样支持可以附带合法的约束。
delegate bool Predicate<T>(T value);
class X
{
static bool F(int i) { }
static bool G(string s) { }
static void Main(string[] args)
{
Predicate<string> p2 = G;
Predicate<int> p1 = new Predicate<int>(F);
}
}
泛型委托支持在委托返回值和参数上应用参数类型,这些参数类型同样支持可以附带合法的约束。
//泛型方法的声明和调用
public class Finder
{
//泛型方法声明
public static int Find<T>(T[] items, T item)
{
for (int i = 0; i < items.Length; i++)
{
if (items[i].Equals(item))
{
return i;
}
}
return -1;
}
}
//泛型方法调用
int i = Finder.Find<int>(new int[] { 1, 3, 4, 5, 6, 8, 9, }, 6);
public class Finder
{
//泛型方法声明
public static int Find<T>(T[] items, T item)
{
for (int i = 0; i < items.Length; i++)
{
if (items[i].Equals(item))
{
return i;
}
}
return -1;
}
}
//泛型方法调用
int i = Finder.Find<int>(new int[] { 1, 3, 4, 5, 6, 8, 9, }, 6);
//泛型方法的重载
class MyClass
{
void F1<T>(T[] a, int i);
void F1<U>(U[] a, int i); //不可以构成重载方法
void F2<T>(int x);
void F2(int x); //可以构成重载
void F3<T>(T t) where T : A;
void F3<T>(T t) where T : B; //不可以构成重载方法
}
class MyClass
{
void F1<T>(T[] a, int i);
void F1<U>(U[] a, int i); //不可以构成重载方法
void F2<T>(int x);
void F2(int x); //可以构成重载
void F3<T>(T t) where T : A;
void F3<T>(T t) where T : B; //不可以构成重载方法
}
//泛型方法的重写,泛型方法被覆盖时,约束被默认继承
abstract class Base
{
public abstract T F<T,U>(T t,U u) where U:T;
}
class Derived : Base
{
public override X F<X, Y>(X x, Y y)
{
}
}
泛型中的约束:基类约束
abstract class Base
{
public abstract T F<T,U>(T t,U u) where U:T;
}
class Derived : Base
{
public override X F<X, Y>(X x, Y y)
{
}
}
class A { public void F1() { } }
class B { public void F2() { } }
class C<S, T>
where S : A // S继承自A
where T : B // T继承自B
{
// 可以在类型为S的变量上调用F1,
// 可以在类型为T的变量上调用F2
}
泛型中的约束:接口约束class B { public void F2() { } }
class C<S, T>
where S : A // S继承自A
where T : B // T继承自B
{
// 可以在类型为S的变量上调用F1,
// 可以在类型为T的变量上调用F2
}
interface IPrintable { void Print();
}
interface IComparable<T> { int CompareTo(T v);}
interface IKeyProvider<T> { T GetKey(); }
class Dictionary<K,V>
where K: IComparable<K>
where V: IPrintable, IKeyProvider<K>
{
// 可以在类型为K的变量上调用CompareTo,
// 可以在类型为V的变量上调用Print和GetKey
}
泛型中的约束:构造器约束}
interface IComparable<T> { int CompareTo(T v);}
interface IKeyProvider<T> { T GetKey(); }
class Dictionary<K,V>
where K: IComparable<K>
where V: IPrintable, IKeyProvider<K>
{
// 可以在类型为K的变量上调用CompareTo,
// 可以在类型为V的变量上调用Print和GetKey
}
class A { public A() { } }
class B { public B(int i) { } }
class C<T>
where T : new()
{
//可以在其中使用T t=new T();
}
C<A> c=new C<A>(); //可以,A有无参构造器
C<B> c=new C<B>(); //错误,B没有无参构造器
泛型中的约束:值/引用类型约束class B { public B(int i) { } }
class C<T>
where T : new()
{
//可以在其中使用T t=new T();
}
C<A> c=new C<A>(); //可以,A有无参构造器
C<B> c=new C<B>(); //错误,B没有无参构造器
public struct A { }
public class B { }
class C<T>
where T : struct
{
// T在这里面是一个值类型
}
C<A> c=new C<A>(); //可以,A是一个值类型
C<B> c=new C<B>(); //错误,B是一个引用类型
学习中,来源李建忠老师PPTpublic class B { }
class C<T>
where T : struct
{
// T在这里面是一个值类型
}
C<A> c=new C<A>(); //可以,A是一个值类型
C<B> c=new C<B>(); //错误,B是一个引用类型