程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C# 2.0 Specification(泛型六)

C# 2.0 Specification(泛型六)

編輯:關於C語言
接泛型五
20.8表達式和語句
某些表達式和語句的操作針對泛型進行了修改。這一節將介紹這些改變。
20.8.1默認值表達式
默認值表達式被用於獲得一個類型的默認值(§5.2)。通常一個默認值表達式被用於類型參數,因為如果類型參數的是一個值類型或引用類型,它可能不是已經的。(不存在從null類型到類型參數的轉換。)
primary-no-array-creation-expression:(基本無數組創建表達式:)

default-value-expression(默認值表達式)
default-value-expression:(默認值表達式:)
primary-expression . default (基本表達式 .default)
predefined-type . default(預定義類型. default)
如果一個基本表達式在一個默認值表達式中被使用,並且這個基本表達式不能分為一個類型,那麼將會出現一個編譯時錯誤。然而在§7.5.4.1中描述的規則也適用於形成E.default的構件。
如果默認值表達式的左邊針對一個引用類型在運行時被計算,結果是將null轉換到那個類型。如果默認值表達式的左邊針對一個值類型在運行時被計算,其結果是值類型的默認值(§4.1.2)。
如果類型是一個具有類約束的引用類型或類型參數,默認值表達式是一個常量表達式(§7.15)。此外,如果類型是下列值之一,默認值表達式是一個常量表達式:sbyte、byte、 short、ushort、 int 、 uint 、long 、ulong 、 char 、float 、double 、decimal 或bool。
20.8.2對象創建表達式
對象常見表達式的類型可以是一個類型參數。當類型參數被作為對象創建表達式中的類型而指定時,下面兩個條件必須具備,否則將會出現編譯時錯誤
實參列表必須刪除
必須為類型參數而指定new()形式的構造函數約束


通過創建一個類型參數被綁定到的運行時類型的實例,並調用該類型的默認構造函數,就可以執行對象創建表達式。運行時類型可以是引用或者值類型。
20.8.3運算符的類型
typeof運算符可以用於類型參數。其結果是被綁定到類型參數的運行時類型的System.Type對象。typeof運算符也可以被用於構造類型。
class X <T>
{
public static void PrintTypes()
{
Console.WriteLine(typeof(T).FullName);
Console.WriteLine(typeof(X<X<T>>).FullName);
}
}
class M
{
static void Main()
{
X<int>.PrintTypes();
}
}
先前的程序將打印如下。
System.Int32
X<X<Sytem.Int32>>
Typeof運算符不能用於沒有指定類型實參的泛型類型聲明的名字。
class X<T>{…}
class M
{
static void Main()
{
Type t = typeof(X); //錯誤,X需要類型實參
}
}
20.8.4引用相等運算符
如果T由一個類約束而約束,引用類型相等運算符可以被用於比較類型參數T的值。
引用類型相等運算符的用法可以讓類型參數T的實參很容易地與其他為null的實參進行比較,即使T沒有類約束也如此。在運行時,如果T是一個值類型,比較的結果將是false。


下面的例子檢查一個非約束類型參數類型的實參是否是null。
class C<T>
{
void F(T x)
{
if(x==null) thow new ArgumentNullException();

}
}

即使是T可以表示一個值類型,x==null構件也是允許的,並且當T是值類型時,其結果被簡單的定義為false。
20.8.5 is運算符
在開放類型上的is運算符操作遵循通常的規則(§7.9.9)。如果e或T的編譯時類型是一個開放類型,那麼在運行時對於e和T將總是執行動態類型檢查。
20.8.6as運算符
只要T有一個類約束,類型參數T可被用在as運算符的右邊。這種限制是需要的,因為值null可能被作為運算符的結果返回。
class X
{
public T F<T>(object o) where T:Attribute
{
return o as T; //ok,T有一個類約束
}
public T G<T>(object o)
{
return o as T; //錯誤,T沒有約束
}
}
在as運算符(§7.9.10)的當前規范中,對於表達式e as T最後一點表明,如果從e的編譯時類型到T,不存在有效的顯式引用轉換,將會出現編譯時錯誤。對於泛型,這條規則稍微作了修改。如果E的編譯時類型或T是一個開放類型,在這種情況下將不會出現編譯時錯誤;相反,運行時檢查將會執行。

20.8.7異常語句
對於開放類型,throw(§8.9.5)和try(§8.10)的通常規則是適用的。


只要類型參數具有System.Exeption異常(或子類具有)作為類約束,那麼throw語句可以被用作其類型有一個類型參數給定的表達式。
只要類型參數System.Exception(或子類子類具有)作為類約束,那麼在catch語句中的命名的類型可能是一個類型參數。

20.8.8 lock語句
lock語句可以被用作其類型由一個類型參數給定的表達式。如果表達式的運行時類型是一個值類型,lock將沒有效果(因為對於裝箱值不能有任何其他的引用)。
20.8.9 using 語句
using 語句(§8.13)遵循通常的規則:表達式必須被隱式的轉換到System.IDisposable。如果類型參數通過System.IDisposable而約束,那麼該類型的表達式可以使用using 語句。
20.8.10 foreach語句
給定如下形式的foreach語句
foreach(ElementType element in collection) statement
如果集合表達式是一個沒有實現集合模式的類型,但為每個類型T實現了構造接口System.Collections.Generic.IEnumerable<T>,那麼foreach語句的擴展是
IEnumerator<T> enumerator = ((IEnuemrable<T>)(collection).GetEnumerator();
try
{
where (enumerator.MoveNext()){
ElementType element = (ElementType)enumerator.Current;
statement;
}
}
finally{
enumerator.Dispose();
}

20.9查找規則修訂
泛型修改了用於查找和綁定名字的某些基本規則。下面幾節在考慮泛型的情況下,重新敘述了所有的基本名字查找規則。


20.9.1命名空間和類型名字
如下內容可替換§3.8。
在C#程序中有幾個上下文需要指定命名空間或者類型名字。任何形式的名字都可以由一個或多個由“.”標記分隔的標識符號組成。
namespace-name:(命名空間名字:)
namespace-or-type-name(命名空間或類型名字)
type-name:(類型名字:)
namespace-or-type-name(命名空間或類型名字)
namespace-or-type-name:(命名空間或類型名字:)
identifIEr type-argument-list opt(標識符 類型實參列表可選)
namespace-or-type-name . identifIEr type-argument-list opt( 命名空間或類型名字. 標識符 類型實參列表可選)
命名空間名字是引用命名空間的命名空間名字或類型名字(namespace-or-type-name)。見下面所描述的決策,命名空間名字的命名空間或類型名字必須引用一個命名空間,否則出現編譯時錯誤。在一個命名空間名字中不能有類型實參(只有類型可以具有類型實參)。
類型名字是一個引用類型的命名空間或類型名字(namespace-or-type-name)。見下面所描述的決策,類型名字的命名空間或類型名字必須引用一個類型,否則出現編譯時錯誤。
命名空間或類型名字的意義按如下確定。
如果命名空間或類型名字是I或I<A1,…,AN>的形式,其中I 是一個單一標識符,並且<A1,…,AN>是一個可選類型實參列表。
- 如果命名空間或類型名字出現在泛型方法聲明之內,並且該聲明包括一個由I給定名字的沒有指定類型實參列表的類型參數,那麼命名空間或類型名字引用該類型參數。
- 否則,如果命名空間或類型名字出現在類型聲明之內,那麼對於類型T的每個實例(<A1,…,AN>20.1.2),以那個類型聲明的實例類型開始,並繼續采用每個封閉類或結構類型聲明(如果有的話)
u 如果沒有指定包含由I給定名字,並且沒有類型實參列表的類型參數T的聲明,那麼命名空間或類型名字引用那個類型參數。



u 否則,如果I是T中可訪問成員的名字,並且如果那個成員是一個帶有匹配類型參數數量的類型,那麼命名空間或類型名字引用類型T.I或者類型T.I<A1,…AN>。注意當確定命名空間或類型名字的意義時,無類型成員(常數、字段、方法、屬性、索引器、運算符、實例構造函數、析構函數和靜態構造函數)和帶有不同數量的類型參數成員將會被忽略。
- 否則,對於在以命名空間或類型名字出現的命名空間開始的每個命名空間N,並繼續使用每個封閉命名空間(如果有的話),然後以全局命名空間結束,下面的步驟將會被計算,直到該實體被定位。
u 如果I 是在N中的命名空間中的名字,並且沒有指定類型實參列表,那麼命名空間或類型名字引用該個命名空間。
u 否則,如果I是在N中帶有匹配類型參數數量的可訪問類型的名字,那麼命名空間或類型名字引用使用給定類型實參構造的類型。
u 否則,如果命名空間或類型名字出現的位置,由N的命名空間聲明所封閉
- 如果命名空間聲明包含一個由I 給定名字的using 別名指令,而I帶有導入命名空間或類型,並且沒有指定參數列表,那麼命名空間或類型名字引用該命名空間或者類型
- 否則,如果由命名空間聲明的using命名空間指示符導入的命名空間,恰好包含帶有I 給定名字的,匹配類型參數數量的類型,那麼命名空間或類型名字引用由給定類型實參構造的這個類型。
- 否則,如果由命名空間聲明的using 命名空間指示符導入的命名空間包含多個帶有I給定名字的,匹配類型參數數量的類型,那麼命名空間或者類型名字是模糊的,並且將導致錯誤。
- 否則,命名空間或類型名字是未定義的,並且出現編譯時錯誤。



l 否則,命名空間或者類型名字是N.I或者N.I<A1,…,AN>的形式,這裡N是一個命名空間或類型名字,I是一個標識符,並且<A1,…,AN>是一個可選類型實參列表。N 被作為命名空間或類型名字而首先決策。如果N的決策失敗,將會出現一個編譯時錯誤。否則N.I或者N.I<A1,…,AN>將按如下方式決策。
- 如果N引用一個命名空間,並且如果I是內嵌在N中的命名空間名字,並且沒有指定類型實參列表,那麼命名空間或類型名字引用該內嵌命名空間。
- 否則,如果N引用一個命名空間,並且I是在帶有匹配類型參數數量的N中的可訪問類型的名字,那麼命名空間或類型名字引用由給定類型實參構造的那個類型。
- 否則,如果N引用類或結構類型,並且I是內嵌在帶有與類型參數匹配的N中的可訪問類型的名字,那麼命名空間或者類型名字引用由給定實參構造的那個類型。
- 否則,N.I是一個無效的命名空間名字,並且會出現編譯時錯誤。

20.9.2成員查找
下面內容可替換§7.3

成員查找是一種根據在上下文中的意義來確定類型的處理過程。在一個表達式中,成員查找可以作為計算一個簡單名字或成員訪問(§20.9.4)而出現。
在類型T中的名字N的成員查找按如下規則確定。
首先一組名為N的可訪問成員被確定。
- 如果T是一個類型參數,那麼在每個作為T的類約束或接口約束而指定的類型,連同在object中的N的命名成員的集合中,這個集合就是命名的可訪問成員的聯合。
- 否則,這個集合由T中的N的所有命名可訪問成員組成,包括繼承成員和在object中的N的命名可訪問成員。如果T 是一個構造類型,成員的集合通過替換§20.5.4中描述的類型實參而得到。包括override修飾符的成員將從集合中排出。




接著,通過其他成員而被隱藏的成員將從這個集合中刪除。對於在集合中的每個成員S.M,S是M在其中被聲明的類型,下面的規則可適用
- 如果M是一個常數、字段、屬性、事件或枚舉成員,那麼在S的所有基類中聲明的成員都將從這個集合刪除。
- 如果M是一個類型聲明,那麼在 S基類中的所有非類型聲明都從集合被刪除,並且,作為S 在基類型中聲明的M的所有帶有相同數量類型參數的類型聲明,都將從該集合中刪除。
- 如果M是一個方法,那麼在S的基類中聲明的所有非方法成員,都將從這個集合刪除,並且,作為S 在基類型中聲明的M的帶有相同簽名的所有方法都將從這個集合中刪除。
接著,通過類成員隱藏的接口成員將從該集合中刪除。這一步,只有當T是一個類型參數,並且T有類約束和多個接口約束時才有效。對於在集合中的每個成員S.M,其中S是M在其中聲明的類型,如果S是一個類聲明而不是object的話,下面的規則適用
- 如果M是一個常數、字段、屬性、事件、枚舉成員或類型聲明,那麼在接口聲明中聲明的所有成員都將從這個集合中刪除。
- 如果M是一個方法,那麼在接口類型中聲明的所有非方法成員都將從這個集合中刪除,並且,作為S 在接口中聲明的M的帶有相同簽名的所有方法都將從這個集合中刪除。
最後,在刪除隱藏成員之後,查找的結果將被確定
- 如果由單一成員組成的集合,不是類型、方法,那麼這個成員就是查找的結果。
- 否則,如果集合只包含方法,那麼這組方法就是查找的結果。
- 否則,如果集合只包含類型聲明,那麼這組類型聲明在成員查找的結果中。
- 否則,查找是不明確的,將會出現編譯時錯誤。
對於類型,而不是類型參數和接口的成員查找來說,在接口中的成員查找是嚴格的單繼承(在繼承鏈中的每個接口恰好有零個或一個直接基接口),查找規則的影響只是派生成員隱藏帶有相同名字和簽名的基類成員。這種單繼承查找是很明確的。成員查找中可能引起的模糊性來自於§13.2.5中描述的多重繼承接口


20.9.3簡單名字
如下內容可替換§7.5.2。
簡單名字由一個標識符,其後可跟隨可選的類型參數列表。
simple-name:(簡單名字:)
identifIEr type-argument-list opt(標識符 類型實參列表可選)
對於I或I<A1,…,AN>形式的簡單名字,這裡I 是一個標識符,I<A1,…,AN>是一個可選類型實參列表,可以被按如下方式計算和分類。
如果簡單名字出現在塊內,並且如果塊的局部變量聲明空間包含由I給定名字的局部變量或參數,那麼,這個簡單名字引用該局部變量和參數,並且作為一個變量而被分類。如果類型實參列表被指定,將會出現編譯時錯誤。
如果簡單名字出現在泛型方法聲明體之內,並且如果該聲明包含由I給定名字的類型參數,那麼簡單名字引用那個類型參數,如果只定了類型實參列表被,將會出現編譯時錯誤。
否則,對於以直接封閉類、結構或枚舉聲明的實例類型開始的類型T的每個實例,繼續采用每個封閉外部類或結構聲明的實例類型(如果有的話)。
- 如果T的聲明包括由 I給定名字的類型參數,那麼,簡單名字引用該類型參數。如果類型實參列表被指定,將會出現編譯時錯誤。
- 否則,如果在T 中I的成員查找產生一個匹配
u 如果T是直接封閉類或結構類型的實例類型, 並且查找標識一個或多個方法,結果將是一個帶有與this表達式關聯的方法組。如果類型實參列表被指定,它被用在一個泛型方法調用中(§20.6.3)。
u 如果T是直接封閉類或結構類型的實例類型,如果查找標識一個實例成員,並且引用出現在一個實例構造函數、實例方法或一個實例訪問器的塊之內,其結果將和this.I形式的成員訪問相似。如果類型實參被指定,將出現編譯時錯誤。
u 否則,結果與T.I或T.I<A1,…,AN>形式的成員訪問相似。在這種情況下,引用實例成員的簡單名字將是一個編譯時錯誤。



否則,對於帶有每個簡單名字出現在其中的命名空間的命名空間N,繼續采用每個封閉命名空間(如果有的話),並以全局命名空間結束,下面的步驟將被計算,直到一個實體被定位。
- 如果I是在N 中的一個命名空間的名字,並且沒有指定類型實參列表,那麼簡單名字將引用該命名空間。
- 否則,如果I是在帶有匹配類型參數數量的N中的一個可訪問類型的名字,那麼簡單類型引用由給定類型實參構造的那個類型。
u 如果命名空間聲明包含一個關聯由I給定名字的using 別名指令,這裡I是一個導入命名空間或類型,並且沒有指定類型實參列表,那麼簡單名字引用該命名空間或類型。
u 否則,如果由命名空間聲明的using 命名空間指令導入的命名空間,恰好包含一個由I給定名字的,匹配類型參數數量的類型,那麼簡單名字引用由給定類型實參構造的類型。
u 否則,如果由命名空間聲明的using命名空間指令導入的命名空間,包含多個由I給定名字,匹配類型參數數量的類型,那麼簡單名字是不明確的,將導致編譯時錯誤
l 否則,由簡單名字給定的名字是未定義的,將導致編譯時錯誤。

20.9.4成員訪問
如下內容可代替§7.5.4。
成員訪問由基本表達式或預定義類型,緊接一個“.”標記,再緊接一個標識符,然後接著可選的類型實參列表而組成。
member-Access:(成員訪問:)
primary-expression . identifIEr type-argument-list opt(基本表達式. 標識符 類型實參列表可選)
predefined-type . identifIEr type-argument-list opt(預定義類型. 標識符 類型實參列表可選)預定義類型:下列之一
bool byte char decimal double float int long
object sbyte short string uint ulong ushort


對於E.I或E.I<A1,…,AN>形式的成員訪問,這裡E是一個基本表達式或預定義類型,I是一個標識符,並且<A1,…,AN>是一個可選類型實參列表,將按如下方式被計算和分類。
如果E 是一個命名空間,I是E 中嵌套命名空間的名字,並且沒有指定類型實參,那麼結果就是這個命名空間。
如果E是一個命名空間,I是在E中可訪問類型的名字,E 匹配類型參數的數量,那麼結果就是由給定類型實參構造的類型。
如果E是一個預定義類型或作為一個類型而被分類的基本表達式,如果E 不是類型參數,並且如果在E中I的成員查找產生一個匹配,那麼E.I被計算,並按如下分類。
- 如果I標識一個或多個類型聲明,那麼使用相同數量的(可能是零)類型參數來確定該類型聲明,就像是在類型實參中提供的那樣。結果就是由給定類型實參而構造的類型。如果類型聲明不匹配類型參數的數量,將出現編譯時錯誤。
- 如果I標識一個或多個方法,那麼結果是沒有關聯實例表達式的方法組。如果類型實參列表被指定,它將在泛型方法調用中被使用(§20.6.3)。
- 如果I 標識一個靜態屬性、靜態字段、靜態事件、常數或一個枚舉成員,並且如果類型實參列表被指定,將出現編譯時錯誤。
- 如果I標識一個靜態屬性,那麼結果是帶有無關聯實例表達式的屬性訪問。
- 如果I標識一個靜態字段
u 如果字段是只讀的,並且引用發生在類或結構的靜態構造函數之外,字段將在這裡被聲明。那麼結果是一個值,也就是在E中靜態字段I的值。
u 否則,結果是一個變量,也就是在E中的靜態字段I。
- 如果I標識一個靜態事件
u 如果引用發生在事件被聲明的類或者結構中,並且事件被聲明時沒有使用事件訪問器聲明(event-Accessor-declaration)(§10.7),那麼E.I就好像I是一個靜態字段一樣被處理。
u 否則,結果是一個無關聯的實例表達式的事件訪問。
- 如果I標識一個常數,那麼結果是值,也就是常數的值。


- 如果I標識一個枚舉成員,那麼結果是一個值,也就是枚舉成員的值。
- 否則,E.I是一個無效成員引用,並將導致編譯時錯誤。

如果E是一個屬性訪問、索引器訪問、變量或值,其類型是T,並且在T中I的成員查找產生一個匹配,那麼E.I按如下方式被計算和分類。
- 首先,如果E是一個屬性或索引器訪問,那麼屬性或索引器訪問的值將被獲得(§7.1.1),並且E被重分類為值。
- 如果I標識一個或多個方法,那麼結果是一個帶有關聯的E的實例表達式的方法組。如果類型實參列表被指定,它將在泛型方法調用中被使用(§20.6.3)。
- 如果I標識一個實例屬性、實例字段或實例事件,並且如果類型實參列表被指定,將產生編譯時錯誤。
- 如果I標識一個實例屬性,那麼結果是一個帶有關聯的E 的實例表達式。
- 如果T是一個類類型並且I 標識一個類類型的實例字段
u 如果E的值是null,那麼將會拋出System.NullReferenceException。
u 否則,如果該字段是只讀的,並且引用出現在字段聲明的類的實例構造函數之外,那麼結果是值,也就是由E引用的對象中 I的值。
u 否則,結果是變量,也就是由E引用的對象中字段I。
- 如果T是一個結構類型,並且I 標識該結構類型的實例字段
u 如果E是一個值,或者如果字段是只讀的,並且引用出現在字段聲明的結構的實例構造函數之外,那麼結果是一個值,也就是由E給定的結構實例中字段I的值。
u 否則,結果是一個變量,也就是由E給定結構實例中的字段I;
- 如果I標識一個實例事件
u 如果引用出現在該事件被聲明的類或結構之內,並且事件被聲明時沒有使用事件訪問器聲明,那麼E.I就好像I是一個實例字段一樣被處理。
u 否則,結果是一個帶有關聯的E的實例表達式。
否則,E.I是一個無效成員引用,將導致編譯時錯誤。



20.9.5方法調用
如下內容可替換§7.5.5.1中描述方法調用的編譯時處理部分。
對於M(A)形式的方法調用的編譯時處理,其中M是一個方法組(可能包含一個類型實參列表),A是可選實參列表,由如下步驟組成。
方法調用的候選集合被構造。對於每個與方法組M關聯的方法F
- 如果F是非泛型的,當如下成立時F是候選項
u M沒有類型實參列表,並且
u 對於A(§7.4.2.1) ,F是適用的。
- 如果F是泛型,並且M沒有類型實參列表,當如下成立時,F是候選項
u 類型推斷成功(§20.6.4),對於調用推斷出類型實參的列表,並且
u 一旦推斷的類型實參替換了對應方法類型參數,F的參數列表對於A是適用的,並且
u 在替換類型實參後,F 的參數列表,與適用的可能以其擴展形式(§7.4.2.1)在相同的類型中作為F而聲明的非泛型方法是不同的。
- 如果F是泛型,並且M包括一個類型實參列表,當如下成立時,F是候選項
u F和在類型實參列表中提供的一樣,具有相同數量的方法類型參數,並且
u 一旦,類型實參替換對應的方法類型參數,F的參數列表對於A 是可適用的(§7.4.2.1)。
候選方法的集合被縮減到只包含從深度派生類型而來的方法:對於在集合中的每個C.F方法,C是F在其中聲明的類型,在C的基類型中聲明的所有方法都被從集合中刪除。
如果候選方法的結果集合是空的,那麼沒有可適用的方法存在,並且會出現編譯時錯誤。如果候選方法並不是在同一類型中聲明的,方法調用將是不明確的,並且會出現編譯時錯誤(這後一種情況,只可能出現在對於一個在具有多重直接基接口的接口中的方法的調用,如§13.2.5的描述)。




候選方法集合的最佳方法使用重載決策規則(§7.4.2)標識。如果一個單一的最佳方法不能被標識,該方法調用是不明確的,並產生編譯時錯誤。當執行重載決策時,泛型方法的參數在將對應的方法類型參數替換為類型實參(提供的或推斷的)之後將被考慮。
被選擇的最佳方法的最後驗證被執行
- 方法在方法組的上下文中是有效的:如果方法是一個靜態方法,方法組必須通過類型源自於簡單名字或成員訪問。如果該最佳方法是一個實例方法,方法組必須通過一個變量或值或者基類訪問(base-Access)源自於簡單名字或成員訪問。如果這些需求都不滿足,那麼將會出現編譯時錯誤。
- 如果該最佳方法是一個泛型方法,類型實參(提供的或推斷的)將被針對聲明在泛型方法之上的約束作出檢查。如果任何類型實參不滿足對應類型參數的約束,將產生一個編譯時錯誤。
一旦方法根據前面的步驟被選擇和驗證,實際的運行時調用將根據§7.4.中的函數成員調用規則而被處理。
20.9.6委托創建表達式
如下內容可替換§7.5.10.3中委托創建表達式的編譯時處理部分。
對於new D(E)形式的委托創建表達式的編譯時處理,其中D 是一個委托類型,E是一個表達式,由如下步驟組成。
如果E是一個方法組
- 對應於E(A)形式的方法調用,一個單一的方法調用將被選擇。
u D的參數類型和修飾符(ref或out)被用作實參類型和實參列表A的修飾符。
u 在適用的測試和類型推斷中,轉換不予考慮。在隱式轉換足夠的實例中,類型要求是同一的。
u 重載決策步驟不會執行。相反,候選的集合必須恰好包含一個與D兼容的方法(接著使用類型實參替換類型參數),並且這個方法將變成新創建委托所引用的方法。如果沒有匹配的方法存在,或有多個匹配的方法存在,將發生編譯時錯誤。



- 如果被選擇的方法是一個實例方法,與E關聯的實例表達式確定委托的目標對象。
- 結果是一個D類型的值,也就是引用選擇的方法和目標對象的新創建委托。
否則,E是一個委托類型的值
- D和E必須兼容;否則出現編譯時錯誤。
- 結果是D類型的值,也就是像E一樣引用相同的調用列表的新創建的委托。
否則,委托創建表達式是無效的,並且出現編譯時錯誤。

20.10右移語法改變
泛型使用“<”和“>”字符分隔類型參數和類型實參(與C++的模板語法相似)。構造類型有時可嵌套,如List<Nullable<int>>,但使用這種構件有一些微妙的語法問題:詞法將組合這個構件的最後兩個標記“>>”(右移運算符),而不是產生句法需要的兩個“>”標記。盡管一個可能的解決方案是在兩個“>>”中放入空格,這也是很尴尬而令人迷惑的,並沒有以任何方式增加程序的簡潔性。
為了讓這些中性的構件維持簡單的詞法,“>>”和“>>=”標記從詞法中刪除了,取代的是右移和右移賦值產生式。
運算符或標點:之一
{ } [ ] ( ) . , : ;
+ - * / % & | ^ ! ~
= < > ? ++ -- && || == ->
!= <= >= += -= *= /= %= &= |=
^= << <<=
right-shift:(右移:)
> >
right-shift-assignment:(右移賦值)
> >=
不像在句法中的其他產生式,在右移和右移賦值產生式的標記之間不允許任何種類的字符存在(甚至是空格)。


下面的產生式被使用右移或右移賦值進行了修改。
shift-expression:(移位表達式:)
additive-expression(附加表達式)
shift-expression << additive-expression(移位表達式 << 附加表達式)
shift-expression right-shift additive-expression(移位表達式 right-shift 附加表達式)
assignment-Operator:(賦值運算符:)
=
+=
-=
*=
/=
%=
&=
|=
^=
<<=
right-shift-assignment
overloadable-binary-Operator:(可重載二元運算符:)
+
-
*
/
%
&
|
^
<<
right-shift
==
!=
>
<
>=
<=

(泛型完)
****************************
終於把這一章貼完了,哎,手都酸了,有問題的地方希望大家多多提出來,千萬別客氣:)
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved