|
這篇文章是翻譯的微軟的技術(shù)文章.供學(xué)習(xí)c#的朋友參考,請(qǐng)勿用于商業(yè)目的。http://msdn.microsoft.com/vcsharp/team/language/default.aspx 由于這一章非常長(zhǎng)可能需要分幾篇:) 20.泛型 20.1泛型類(lèi)聲明 泛型類(lèi)聲明是一個(gè)需要提供類(lèi)型參數(shù)以形成實(shí)際類(lèi)型的類(lèi)的聲明。
類(lèi)聲明可以有選擇地定義類(lèi)型參數(shù)。
class-declaration: (類(lèi)聲明)
attributesopt class-modifiersopt class identifieropt type-parameter-listopt class –baseopt type-parameter-constraints-clauseopt class-body;opt (特性可選 類(lèi)修飾符可選 類(lèi)標(biāo)識(shí)符可選 類(lèi)型參數(shù)列表可選 基類(lèi)可選 類(lèi)型參數(shù)約束語(yǔ)句可選 類(lèi)體; 可選 )
除非提供了類(lèi)型參數(shù)列表,類(lèi)聲明可以不提供類(lèi)型參數(shù)化約束語(yǔ)句。
提供了類(lèi)型參數(shù)列表的類(lèi)聲明是一個(gè)泛型類(lèi)聲明。此外,任何嵌入到泛型類(lèi)聲明或泛型結(jié)構(gòu)聲明中的類(lèi),自身是一個(gè)泛型類(lèi)聲明,因?yàn)楸仨毺峁┌?lèi)型的類(lèi)型參數(shù)以創(chuàng)建構(gòu)造類(lèi)型(constructed type);
泛型類(lèi)通過(guò)使用構(gòu)造類(lèi)型而被引用(§20.5)。給定泛型類(lèi)聲明
class List<T>{}
這是構(gòu)造類(lèi)型的一些例子,List<T>,List<int>和List<List<string>>。構(gòu)造類(lèi)型可以使用一個(gè)或多個(gè)參數(shù),例如List<T>被稱(chēng)為開(kāi)放構(gòu)造類(lèi)型(open constructed type)。不使用類(lèi)型參數(shù)的構(gòu)造類(lèi)型,例如List<int>被稱(chēng)為封閉構(gòu)造類(lèi)型(closed constructed type)。
泛型類(lèi)型不可以被“重載”;也就是說(shuō),和普通類(lèi)型一樣在一個(gè)作用域內(nèi),泛型類(lèi)型必須被唯一地命名。
class C{}
class C<V>{}//錯(cuò)誤,C定義了兩次
class C<U,V>{}//錯(cuò)誤,C定義了兩次
然而在非限定類(lèi)型名字查找(§20.9.3)中使用的類(lèi)型查找規(guī)則和成員訪問(wèn)(§20.9.4),確實(shí)考慮到了類(lèi)型參數(shù)的個(gè)數(shù)。
20.1.1類(lèi)型參數(shù) 類(lèi)型參數(shù)可以在一個(gè)類(lèi)聲明上提供。每個(gè)類(lèi)型參數(shù)是一個(gè)簡(jiǎn)單的標(biāo)識(shí)符,它指示了用來(lái)創(chuàng)建一個(gè)構(gòu)造類(lèi)型的類(lèi)型參數(shù)的占位符。類(lèi)型參數(shù)是在后面將要被提供的類(lèi)型的形式占位符。相反,類(lèi)型參數(shù)§20.5.1)只是在構(gòu)造類(lèi)型被引用時(shí),實(shí)際類(lèi)型的一個(gè)替代。
type-parameter-list:(類(lèi)型參數(shù)列表:)
<type-parameters> (<類(lèi)型參數(shù)>)
type-parameters:(類(lèi)型參數(shù):)
type-parameter(類(lèi)型參數(shù))
type-parameters type-parameter(類(lèi)型參數(shù),類(lèi)型參數(shù))
type-parameter:(類(lèi)型參數(shù):)
attributesopt identifier(特性可選 標(biāo)識(shí)符)
在類(lèi)聲明中的每個(gè)類(lèi)型參數(shù)在類(lèi)的聲明空間(§3.3)定義了一個(gè)名字。由此,它不能和另一個(gè)類(lèi)型參數(shù)或在類(lèi)中聲明的成員有同樣的名字。類(lèi)型參數(shù)不能和類(lèi)型自身有同樣的名字。
在一個(gè)類(lèi)中的類(lèi)型參數(shù)的作用域(§3.7),包括基類(lèi) 、 類(lèi)型參數(shù)約束語(yǔ)句和類(lèi)體。不像類(lèi)的成員,它沒(méi)有擴(kuò)展到派生類(lèi)。在其作用域之內(nèi),類(lèi)型參數(shù)可以被用作一個(gè)類(lèi)型。
type(類(lèi)型):
value-type(值類(lèi)型)
reference-type(引用類(lèi)型)
type-parameter(類(lèi)型參數(shù))
由于類(lèi)型參數(shù)可以被許多不同的實(shí)際類(lèi)型實(shí)參所實(shí)例化,類(lèi)型參數(shù)與其他類(lèi)型相比將略微有一些不同的操作和限制。包括如下內(nèi)容。
類(lèi)型參數(shù)不能用于直接聲明一個(gè)基類(lèi)型或者接口 對(duì)于在類(lèi)型參數(shù)上的成員查找規(guī)則,如果約束存在,則依賴于應(yīng)用到該類(lèi)型參數(shù)的約束。更詳細(xì)地說(shuō)明參看§20.7.4。
類(lèi)型參數(shù)可行的轉(zhuǎn)換依賴于應(yīng)用到該類(lèi)型參數(shù)上的約束(如果有的話)。詳細(xì)地說(shuō)明參看§20.7.4。 字面null不能被轉(zhuǎn)換到由類(lèi)型參數(shù)所給定的類(lèi)型,除非類(lèi)型參數(shù)是由一個(gè)類(lèi)約束(§20.7.4)所約束。然而可以使用一個(gè)默認(rèn)值表達(dá)式(§20.8.1)代替。此外,由一個(gè)類(lèi)型參數(shù)給定的類(lèi)型的值可以使用“==”和“!=”(§20.8.4)與null進(jìn)行比較。 如果類(lèi)型參數(shù)通過(guò)一個(gè)構(gòu)造函數(shù)約束(constructor-constraint)(§20.7)而約束,new表達(dá)式只能用過(guò)一個(gè)類(lèi)型參數(shù)而被使用。 類(lèi)型參數(shù)不能用于特性內(nèi)的任何地方。 類(lèi)型參數(shù)不能用于成員訪問(wèn),或者表示一個(gè)靜態(tài)成員或者嵌套類(lèi)型的類(lèi)型名字(§20.9.1、§20.9.4)。 在不安全代碼中,類(lèi)型參數(shù)不能被用作托管類(lèi)型(§18.2)。 作為一種類(lèi)型,類(lèi)型參數(shù)純粹只是一個(gè)編譯時(shí)構(gòu)件。在運(yùn)行時(shí),每個(gè)類(lèi)型參數(shù)被綁定到運(yùn)行時(shí)類(lèi)型,它是通過(guò)泛型類(lèi)型聲明所提供的類(lèi)型實(shí)參所指定的。為此,在運(yùn)行時(shí),使用類(lèi)型參數(shù)聲明的變量類(lèi)型是一個(gè)封閉類(lèi)型(closed type)(§20.5.2)。所有語(yǔ)句和表達(dá)式在運(yùn)行時(shí)執(zhí)行所使用的類(lèi)型參數(shù),都是由那個(gè)參數(shù)作為類(lèi)型實(shí)參而提供的實(shí)際類(lèi)型。
20.1.2實(shí)例類(lèi)型 每個(gè)類(lèi)聲明都有與之關(guān)聯(lián)的構(gòu)造類(lèi)型,即實(shí)例類(lèi)型(instance type)。對(duì)于一個(gè)泛型類(lèi)聲明,實(shí)例類(lèi)型通過(guò)創(chuàng)建一個(gè)來(lái)自于類(lèi)型聲明的構(gòu)造類(lèi)型(§20.4)而形成,它使用對(duì)應(yīng)于類(lèi)型參數(shù)的每一個(gè)類(lèi)型實(shí)參。由于實(shí)例化類(lèi)型使用類(lèi)型參數(shù),在類(lèi)型參數(shù)作用域內(nèi)(類(lèi)聲明之內(nèi)),它是唯一有效的。實(shí)例類(lèi)型在類(lèi)聲明中是this的類(lèi)型。對(duì)于非泛型類(lèi),實(shí)例類(lèi)型只是一個(gè)聲明類(lèi)型。下面展示了幾個(gè)聲明類(lèi),以及它們的實(shí)例類(lèi)型。
class A<T> //實(shí)例類(lèi)型:A<T>
{
class B{} //實(shí)例類(lèi)型:A<T>.B
class C<U>{} //實(shí)例類(lèi)型:A<T>.C<U>
}
class D{} //實(shí)例類(lèi)型:D
20.1.3基類(lèi)規(guī)范 在類(lèi)聲明中指定的基類(lèi)可以是一個(gè)構(gòu)造類(lèi)型(§20.5)。一個(gè)基類(lèi)其自身不能是一個(gè)類(lèi)型參數(shù),但在其作用域內(nèi)可以包含類(lèi)型參數(shù)。
class Extend<V>: V{}//錯(cuò)誤,類(lèi)型參數(shù)被用作基類(lèi)
泛型類(lèi)聲明不能使用System.Attribute作為直接或間接基類(lèi)。
在一個(gè)類(lèi)聲明中指定的基接口可以是構(gòu)造接口類(lèi)型(§20.5);涌谧陨聿荒苁穷(lèi)型參數(shù),但在其作用域內(nèi)可以包含類(lèi)型參數(shù),下面的代碼演示了如何實(shí)現(xiàn)和擴(kuò)展構(gòu)造類(lèi)型。
class C<U,V>{}
Interface I1<V>{}
class D:C<string , int>,I1<string>{}
class E<T>:C<int,T> ,I1<T>{}
泛型類(lèi)型聲明的基接口必須滿足§20.3.1中所描述的唯一性規(guī)則。
從基類(lèi)或接口重寫(xiě)或?qū)崿F(xiàn)方法的類(lèi)的方法,必須提供特定類(lèi)型的合適方法。下面的代碼演示了方法如何被重寫(xiě)和實(shí)現(xiàn)。這將會(huì)在§20.1.10中進(jìn)一步解釋。
class C<U,V>
{
public virtual void M1(U x , List<V> y){…}
}
interface I1<V>
{
V M2(V x);
}
class D:C<string , int>,I1<string>
{
public override void M1(string x , List<int> y){…}
public string M2(string x){…}
}
20.1.4泛型類(lèi)的成員 泛型類(lèi)的所有成員都可以直接地或者作為構(gòu)造類(lèi)型的一部分,從任何封閉類(lèi)(enclosing class)中使用類(lèi)型參數(shù)。當(dāng)特定的封閉構(gòu)造類(lèi)型在運(yùn)行時(shí)被使用時(shí),類(lèi)型參數(shù)的每次使用都由構(gòu)造類(lèi)型所提供的實(shí)際類(lèi)型實(shí)參所代替。例如
class C<V>
{
public V f1;
public C<V> f2=null;
public C(V x){
this.f1 = x;
this.f2 = this;
}
}
class Application
{
static void Main(){
C<int> x1= new C<int >(1);
Console.WriteLine(x1.f1); //打印1
C<double> x2 = new C<double>(3.1415);
Console.WriteLine(x2.f1); //打印 3.1415
}
}
在實(shí)例函數(shù)成員之內(nèi),this的類(lèi)型就是聲明的實(shí)例類(lèi)型(§20.1.2)。
除了使用類(lèi)型參數(shù)作為類(lèi)型和成員,在泛型類(lèi)聲明中也遵循和非泛型類(lèi)成員相同的規(guī)則。適用于特定種類(lèi)成員的附加規(guī)則將在后面幾節(jié)進(jìn)行討論。
20.1.5泛型類(lèi)中的靜態(tài)字段 在一個(gè)泛型類(lèi)聲明中的靜態(tài)變量,在相同封閉構(gòu)造類(lèi)型(§20.5.2)所有實(shí)例中被共享,但在不同封閉構(gòu)造類(lèi)型的實(shí)例中[1],是不被共享的。這些規(guī)則不管靜態(tài)變量的類(lèi)型包含那種類(lèi)型參數(shù)都適用。
例如
class C<V>
{
static int count = 0;
public C()
{
count++;
}
public static int Count{
get{return count;}
}
}
class Application
{
static void Main()
{
C<int> x1 = new C<int>();
Console.WriteLine(C<int>.Count);//打印 1
C<double> x2 = new C<double>();
Console.WriteLine(C<int>.Count);//打印 1
C<int> x3 = new C<int>();
Console.WriteLine(C<int>.Count);//打印 2
}
}
--------------------------------------------------------------------------------
[1] 這是很容易理解的,因?yàn)樵谶\(yùn)行時(shí),不同的封閉構(gòu)造類(lèi)型,是屬于不同的類(lèi)型,比如List<int> 和List<string> 這二者的實(shí)例是不能共享靜
|
溫馨提示:喜歡本站的話,請(qǐng)收藏一下本站!