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是一個引用類型

浙公網安備 33010602011771號