c#2.0的新特性--泛型
c#2.0中引入了許多新的語言特性:比較重要的有4個,泛型(Generics)、匿名方法(Annorymous Methods)、迭代器(Iterators)、和局部類(Partial Types).
? 泛型
? 是c#2.0中最強大的功能。
? 特點一:通過泛型可以定義類型安全的數據結構,而無需使用具體實際的數據類型,著能夠顯著提高性能并得到高質量的代碼。在概念上,反省類似于C++模板,但是在實現和功能方面存在明顯差異。
? 特點二:泛型通過把類型參數化來達到代碼重用的目標,這一特性可以應用在類、結構、接口、委托、方法的設計之中。泛型除了可以大幅提高代碼復用性外,
? 特點三:還可以提供編譯期間的類型檢查,減少不必要的顯式類型轉換,減少不必要的裝箱操作,從而提高應用程序的運行效率。
? 1. 引入泛型的原因:
?? 一般情況下,在通用的數據結構中(例如Stack,List,Dictionory等)存儲的數據,要求必須有相同的數據類型。如果必須存儲不同類型的數據,那么唯一的方法就是將所有的數據首先裝箱為object 類型,然后再存儲。
? 例如,下面的Stack類將其所有的數據存儲在一個object類型的數組中,該類型的兩個方法分別使用object來獲取和返回數據:
public class Stack
{
??? object[] items;
??? public void Push(object item) {...}
??? public object Pop() {...}
}
這樣做的缺點:
第一是性能:根據裝箱和堆棧的功能,使用Push方法能夠想堆棧中壓入任何類型的值,然而,再重新獲取堆棧中的數據值時必須在使用Pop方法拆箱的同時,使用顯式類型轉換得到合適的數據類型。這種裝箱和拆箱的操作增加了執行的負擔,因為它帶來了動態內存分配和運行時類型檢查。
第二是類型安全。因為編譯器允許在任何類型和Object之間進行強制類型轉換,所以將造成編譯時類型安全的不足。主要是Stack類無法強制設置堆棧中的數據類型。
第三是工作效率。編寫類型特定的數據結構以及冗繁的的轉換代碼是一項乏味重復的且易于出錯的工作 。
為了有效解決以上問題,c#2.0引入了泛型。
2.泛型概述
? 泛型常見于集合應用中,在。net2.0框架的類庫中,提供了一個新的名空間System.Collections.Generic,其中包含了一些新的基于泛型的容器類,例如,System.Collectinos.Generic.Stack,System.Collections.Dictionary,Collections.Generic.List,System.Collections.Generic.Queue
等,這些類庫可以在集合中實現泛型。
?? 以堆棧中實現泛型為例
?? Stack類示意代碼:
?? public class Stack<T>
?? {
??????? T[] items;
??????? int count;
????????public void Push(T item) {...}
????????public T Pop() {...}
??? }
?? Stack類應用代碼:
??? //實例化Stack類
??? Ststem.Collections.Genric.Stack<string> stringStack = new System.Collections.Generic.Stack<string>;
?? //增加數據
?? stringStack.Push("硬盤");
?? stringStack.Push("聲卡");
?? stringStack.Push("電源");
?? //轉換為數組
?? Araay stringArray;
?? stringArray = stringStack.ToAraay();
?? //顯示數據
?? foreach(string item in stringArray)
{
?? Console.WriteLine(item);
}
3.約束
為了提供更強大的編譯期間的類型檢查和減少類型轉換,c#允許一個可選的為每個類型參數提供的約束列表。一個類型參數的約束指定了一個類型必須遵守的要求,使得這個類型參數能夠作為一個變量來使用。約束有關鍵字where來聲明,后跟類型參數的名字,再后是一個類或接口 類型的列表,或者構造器約束new().
比如要想使Dictionary<K,V>類能保證鍵值始終實現IComparable接口,類的聲明中應該對類型參數K指定一個約束
public class Dictionary<K,V> where K: IComparable
{
????????????public void Add(K key, V value)
????????????{
??????????????????...
??????????????????if(key.CompareTo(x) < 0 )?? {....}
??????????????????...
????????????}
}
類型參數約束的使用要小心。盡管它們提供了更強大的編譯期間的類型檢查并在一些情況下改進了性能,它還是限制了泛型類型的使用。比如一個泛型類List<T>可能約束T實現IComparable接口,以便Sort方法能夠比較其中的元素。然而這么做的結果使得List<T>不能用于那些不能實現IComparable接口的類型,盡管在某些情況下Sort方法從沒有被實際調用過。
4。泛型類型的成員
class C<V>
{
??? public V f1; //聲明字段
??? public D<V> f2; //作為其他泛型類型 的參數
??? public C<V x>
??? {
?????? this.f1 = x;
??? }
}
??? 泛型類型的成員可以使用泛型類型聲明中的類型參數。但類型參數如果沒有任何約束,則只能在該類型上使用從System.Object繼承的共有成員。
5.泛型接口
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){}
}
6.泛型委托
delegate bool Predicate<T>(T value);
class X
{
???? static bool F(int i){...}
???? static bool G(string s){...}
???? static void Main()
???? {
????????? Predicate<string> p2 = G;
????????? Predicate<int> p1 = new Predicate<int>(F);
???? }
}
???? 泛型委托支持返回值和參數哂納感應用參數類型,這些參數類型同樣可以附帶合法的約束。
7.泛型方法的簡介
??? C#泛型機制只支持“在方法聲明上包含類型參數” -- 即泛型方法。
??? C#泛型機制不支持在除方法外的其他成員(包括屬性、事件、索引器、構造器、析構器)的聲明上包含類型參數,但這些成員本身可以包含在泛型類型中,并使用泛型類型的類型參數。
??? 泛型方法既可以包含在泛型類型中,也可以包含在非泛型類型中。
8.泛型方法的聲明與調用
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<T>(new int[]{1,3,4,5,6,8,9},6);
泛型編程
9.泛型方法的重載
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;
}
10.泛型方法的重寫
abstract class Base
{
??? public abstract T F<T,U>(T t,U u) where U : T;
??? public abstract T G<T>(T t) where U : IComparable;
}
class Derived:Base
{
??? // 合法的重寫,約束被默認繼承
??? public override X F(X,Y)(X x,Y y){}
??? // 非法的重寫,指定任何約束都是多余的
??? public override T G<T>(T t) where T : Comparable{}
}
11.泛型約束簡介
??? C#泛型要求對"所有泛型類型或泛型方法的類型參數"的任何假定,都要基于"顯式的約束",以維護C#所要求的類型安全.
??? "顯式約束"有where字句表達,可以指定"基類約束","接口約束","構造器約束","值類型/引用類型約束"共四中約束.
??? "顯示約束"并非必須,如果沒有指定"顯式約束",泛型類型參數將只能訪問System.Object類型中的公有方法.
基類約束
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
}
接口約束
interface IPrintable{coid Print();}
interface IComparable<T>{int CompareTo(T v);}
interface IKeyProvider<T>{T HetKey();}
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沒有無參數構造器
值類型/引用類型約束
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是一個引用類型
12.總結
??? C#的泛型能力有CLR在運行時支持,它既不同于c++在編譯時所支持的靜態模板,也不同于java在編譯器層面使用"檫拭法"支持的簡單的類型.
??? C#的泛型支持包括類,結構,接口,委托共四種泛型類型,以及方法成員.
??? C#的泛型采用"基類,接口,構造器,值類型/引用類型"的約束方式來實現對類型參數的"顯式約束",它不支持C++模板那樣的基于簽名的顯式約束.
轉載于:https://www.cnblogs.com/zgqys1980/archive/2006/10/10/525529.html
總結
以上是生活随笔為你收集整理的c#2.0的新特性--泛型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基本 SQL 之增删改查
- 下一篇: Java快速入门-01-基础篇