国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > 綜合 > 正文

C# 編程語言的未來功能 2

2024-07-21 02:25:03
字體:
供稿:網(wǎng)友
聲明約束
在 c# 中,程序可以為泛型類中聲明的每個(gè)類型參數(shù)提供可選約束列表。約束表示要將一個(gè)類型構(gòu)造成泛型所必須滿足的要求。可以使用 where 關(guān)鍵字聲明約束,該關(guān)鍵字后跟“參數(shù)-要求”對(duì),其中“參數(shù)”必須是泛型中定義的某個(gè)參數(shù),“要求”必須是類或接口。

為了滿足在 dictionary 類中使用 compareto 方法的需要,程序可以對(duì) keytype 類型參數(shù)添加約束,要求傳遞給 dictionary 類作為第一個(gè)參數(shù)的任何類型都必須實(shí)現(xiàn) icomparable 接口,例如:

public class dictionary<keytype, valtype> where keytype : icomparable
{
   public void add(keytype key, valtype val)
   {
      ...
      switch(key.compareto(x))
      {
      }
      ...
   }
}
這樣,編譯代碼時(shí)就會(huì)檢查代碼,以確保程序每次使用 dictionary 類時(shí),作為第一個(gè)參數(shù)傳遞的類型都實(shí)現(xiàn)了 icomparable 接口。此外,程序在調(diào)用 compareto 方法之前,再也無需將變量顯式轉(zhuǎn)換為 icomparable 接口了。

多重約束

對(duì)于任何給定的類型參數(shù),程序可以為其指定任意多個(gè)接口約束,但最多只能指定一個(gè)類約束。每個(gè)新約束都以另一個(gè)“參數(shù)-要求”對(duì)的形式進(jìn)行聲明,并且給定的泛型的每個(gè)約束都用逗號(hào)分隔。以下示例中的 dictionary 類包含兩種參數(shù),keytype 和 valtype。keytype 類型參數(shù)有兩個(gè)接口約束,而 valtype 類型參數(shù)有一個(gè)類約束:

public class dictionary<keytype, valtype> where
keytype : icomparable,
keytype : ienumerable,
valtype : customer
{
   public void add(keytype key, valtype val)
   {
      ...
      switch(key.compareto(x))
      {
      }
      ...
   }
}
運(yùn)行時(shí)的泛型
泛型類的編譯方法與常規(guī)類的編譯方法幾乎沒有差別。事實(shí)上,編譯結(jié)果只不過是元數(shù)據(jù)和中間語言 (il)。當(dāng)然,為了接受代碼中用戶提供的類型,應(yīng)對(duì) il 進(jìn)行參數(shù)化。根據(jù)提供的類型參數(shù)是值類型還是引用類型,泛型的 il 的用法會(huì)有所不同。

當(dāng)將值類型作為參數(shù)首次構(gòu)造泛型時(shí),運(yùn)行時(shí)將使用提供的參數(shù)替換 il 中的相應(yīng)位置來創(chuàng)建一個(gè)專用的泛型。針對(duì)每個(gè)用作參數(shù)的唯一值類型,將一次性創(chuàng)建專用的泛型。

例如,假設(shè)程序代碼聲明了一個(gè)由整數(shù)構(gòu)造的 stack:

stack<int> stack;
此時(shí),運(yùn)行時(shí)將生成一個(gè)專用的 stack 類,并用整數(shù)替換此類的相應(yīng)參數(shù)。現(xiàn)在,無論程序代碼何時(shí)使用整數(shù) stack,運(yùn)行時(shí)都將重復(fù)使用生成的專用 stack 類。以下示例將創(chuàng)建整數(shù) stack 的兩個(gè)實(shí)例,每個(gè)實(shí)例均使用由此整數(shù) stack 的運(yùn)行時(shí)所生成的代碼來創(chuàng)建:

stack<int> stackone = new stack<int>();
stack<int> stacktwo = new stack<int>();
但是,如果在程序代碼中的其他位置又創(chuàng)建了一個(gè) stack 類,并使用不同的值類型(例如長整型或用戶定義的結(jié)構(gòu))作為其參數(shù),則運(yùn)行時(shí)將生成其他形式的泛型,而這時(shí)會(huì)替換 il 相應(yīng)位置中的長整型參數(shù)。為使用值類型構(gòu)造的泛型創(chuàng)建專用類的優(yōu)點(diǎn)是可以獲得更好的性能。畢竟每個(gè)專用的泛型類都是在“本地”包含值類型,因此不必再進(jìn)行轉(zhuǎn)換。

泛型與引用類型的工作方式稍有不同。首次使用任何引用類型構(gòu)造泛型時(shí),運(yùn)行時(shí)用對(duì)象引用替換 il 中的參數(shù)來創(chuàng)建專用的泛型。之后,每當(dāng)使用引用類型作為參數(shù)實(shí)例化構(gòu)造的類型時(shí),無論構(gòu)造的是何種類型,運(yùn)行時(shí)都會(huì)重復(fù)使用先前創(chuàng)建的專用泛型。

例如,假設(shè)有兩個(gè)引用類型,customer 類和 order 類,并進(jìn)一步假設(shè)您創(chuàng)建了 customer 類型的 stack:

stack<customer> customers;
此時(shí),運(yùn)行時(shí)將生成專用 stack 類,該類并不存儲(chǔ)數(shù)據(jù),而是存儲(chǔ)隨后填充的對(duì)象引用。假設(shè)下一行代碼創(chuàng)建了一個(gè)其他引用類型的 stack,稱為 order:

stack<order> orders = new stack<order>();
與值類型不同,沒有為 order 類型創(chuàng)建另一個(gè)專用的 stack 類,而是創(chuàng)建了專用 stack 類的實(shí)例并設(shè)置 orders 變量來引用它。對(duì)于替換類型參數(shù)的每個(gè)對(duì)象引用,按照 order 類型的大小分配內(nèi)存空間,并將指針設(shè)置為引用該內(nèi)存位置。假設(shè)您隨后遇到了一行用于創(chuàng)建 customer 類型的 stack 的代碼:

customers = new stack<customer>();
同上一個(gè)使用 order 類型創(chuàng)建的 stack 類一樣,創(chuàng)建了專用 stack 類的另一個(gè)實(shí)例,并將其中包含的指針設(shè)置為引用 customer 類型大小的內(nèi)存區(qū)域。由于不同的程序在引用類型的數(shù)量上存在著很大差異,因此泛型的 c# 實(shí)現(xiàn)通過將引用類型的數(shù)量減少到編譯器為引用類型的泛型類創(chuàng)建的專用類數(shù)量,大大降低了代碼的膨脹速度。

此外,當(dāng)使用類型參數(shù)(無論是值類型還是引用類型)實(shí)例化泛型 c# 類時(shí),可以在運(yùn)行時(shí)使用反射和實(shí)際類型進(jìn)行查詢,并且可以確定其類型參數(shù)。

c# 泛型與其他實(shí)現(xiàn)之間的差異

c++ 模板與 c# 泛型存在著顯著的差別。c# 泛型被編譯成 il,這使得在運(yùn)行時(shí)會(huì)智能地為每個(gè)值類型創(chuàng)建相應(yīng)的專用類型,而為引用類型只會(huì)創(chuàng)建一次專用類型;c++ 模板實(shí)際上是代碼擴(kuò)展宏,它為提供給模板的每個(gè)類型參數(shù)生成一個(gè)專用類型。因此,當(dāng) c++ 編譯器遇到模板(例如整數(shù) stack)時(shí),它會(huì)將模板代碼擴(kuò)展為 stack 類并將整數(shù)作為該類本身的類型包含在其中。無論類型參數(shù)是值類型還是引用類型,如果不專門設(shè)計(jì)鏈接器來降低代碼膨脹速度,c++ 編譯器每次都會(huì)創(chuàng)建一個(gè)專用類,從而導(dǎo)致比使用 c# 泛型更顯著的代碼膨脹速度。

而且,c++ 模板不能定義約束。c++ 模板只能通過使用一個(gè)成員(可能屬于也可能不屬于類型參數(shù)),隱式定義約束。如果最終傳遞給泛型類的類型參數(shù)中存在該成員,程序?qū)⒄_\(yùn)行。否則,程序?qū)⑹。⒖赡芊祷仉[藏的錯(cuò)誤信息。由于 c# 泛型可以聲明約束,并且具有嚴(yán)格的類型,因此不存在這些潛在的錯(cuò)誤。

現(xiàn)在,sun microsystems® 已經(jīng)在新版本的 java 語言(代碼名稱為“tiger”)中添加了其他的泛型。sun 選擇的實(shí)現(xiàn)不需要修改 java 虛擬機(jī)。因此,sun 面臨著如何在未修改的虛擬機(jī)上實(shí)現(xiàn)泛型的問題。

提出的 java 實(shí)現(xiàn)使用與 c++ 中的模板和 c# 中的泛型類似的語法,包括類型參數(shù)和約束。然而,由于它處理值類型與處理引用類型的方式不一樣,因此未修改的 java 虛擬機(jī)不支持值類型的泛型。因此,java 中的泛型無法得到有效的執(zhí)行。事實(shí)上,java 編譯器會(huì)在需要返回?cái)?shù)據(jù)時(shí),從指定的約束(如果聲明了)或基本對(duì)象類型(如果未聲明約束)插入自動(dòng)向下的類型轉(zhuǎn)換。此外,java 編譯器將在運(yùn)行時(shí)生成一個(gè)專用類型,然后使用它實(shí)例化任何構(gòu)造類型。最后,由于 java 虛擬機(jī)本身不支持泛型,因此無法在運(yùn)行時(shí)確定泛型實(shí)例的類型參數(shù),而且反射的其他用途也會(huì)受到嚴(yán)重限制。

其他語言中的泛型支持
microsoft 的目標(biāo)是在 visual j#(tm)、visual c++ 和 visual basic 中支持使用和創(chuàng)建泛型。盡管不同語言實(shí)現(xiàn)此功能的時(shí)間有早有晚,但 microsoft 的所有其他三種語言都將包含對(duì)泛型的支持。同時(shí),c# 小組正努力在泛型的基礎(chǔ)運(yùn)行時(shí)中加入相應(yīng)的功能,為實(shí)現(xiàn)多語言支持奠定基礎(chǔ)。microsoft 與第三方語言合作伙伴緊密協(xié)作,以確保在基于 .net 的語言中創(chuàng)建和使用泛型。

迭代程序
迭代程序是基于研究語言中的類似功能(例如 clu、sather 和 icon)而構(gòu)造的語言。簡單說來,通過迭代程序,類型可輕松地聲明 foreach 語句對(duì)其元素進(jìn)行迭代的方式。

為什么需要迭代程序
現(xiàn)在,如果類需要使用 foreach 循環(huán)結(jié)構(gòu)支持迭代操作,則它們必須實(shí)現(xiàn)“枚舉器模式”。例如,編譯器將左側(cè)的 foreach 循環(huán)結(jié)構(gòu)擴(kuò)展為右側(cè)的 while 循環(huán)結(jié)構(gòu):

list list = ...;
foreach(object obj in list)
{
dosomething(obj);
}


enumerator e = list.getenumerator();
while(e.movenext())
{
   object obj = e.current;
   dosomething(obj);




值得注意的是,為了使 foreach 循環(huán)能夠正常運(yùn)行,list 數(shù)據(jù)結(jié)構(gòu)(所迭代的實(shí)例)必須支持 getenumerator 函數(shù)。創(chuàng)建 list 數(shù)據(jù)結(jié)構(gòu)后,必須實(shí)現(xiàn) getenumerator 函數(shù),以返回 listenumerator 對(duì)象:

public class list
{
   internal object[] elements;
   internal int count;

   public listenumerator getenumerator()
   {
      return new listenumerator(this);
   }
}
所創(chuàng)建的 listenumerator 對(duì)象不僅必須實(shí)現(xiàn) current 屬性和 movenext 方法,而且還必須維護(hù)其內(nèi)部狀態(tài),以便程序在每次執(zhí)行該循環(huán)時(shí)都可以移到下一項(xiàng)。此內(nèi)部狀態(tài)機(jī)對(duì)于 list 數(shù)據(jù)結(jié)構(gòu)而言比較簡單,但對(duì)于需要遞歸循環(huán)的數(shù)據(jù)結(jié)構(gòu)(例如二叉樹)來說,該狀態(tài)機(jī)將相當(dāng)復(fù)雜。

由于實(shí)現(xiàn)此枚舉器模式需要開發(fā)人員投入大量的精力并編寫大量代碼,因此 c# 包含一種新的結(jié)構(gòu),使得類可以輕松地指示 foreach 循環(huán)對(duì)其內(nèi)容進(jìn)行迭代的方式。

定義迭代程序
由于迭代程序是 foreach 循環(huán)結(jié)構(gòu)的邏輯對(duì)應(yīng)物,因此其定義方式類似于函數(shù):使用 foreach 關(guān)鍵字并在后面帶有一對(duì)圓括號(hào)。在以下示例中,程序?qū)?list 類型聲明一個(gè)迭代程序。迭代程序的返回類型由用戶決定,但是由于 list 類內(nèi)部存儲(chǔ)的是對(duì)象類型,因此以下迭代程序示例的返回類型為對(duì)象:

public class list
{
   internal object[] elements;
   internal int count;

   public object foreach()
   {
   }
}
值得注意的是,實(shí)現(xiàn)枚舉器模式后,程序需要維護(hù)內(nèi)部狀態(tài)機(jī)以便跟蹤程序在數(shù)據(jù)結(jié)構(gòu)中的位置。迭代程序具有內(nèi)置狀態(tài)機(jī)。使用新的 yield 關(guān)鍵字,程序可以將值返回到調(diào)用該迭代程序的 foreach 語句。當(dāng) foreach 語句下次循環(huán)并再次調(diào)用迭代程序時(shí),此迭代程序?qū)⒃谏弦粋€(gè) yield 語句停止的位置開始執(zhí)行。在以下示例中,程序?qū)⑸扇齻€(gè)字符串類型:

public class list
{
   internal object[] elements;
   internal int count;

   public string foreach()
   {
      yield "microsoft";
      yield "corporation";
      yield "developer division";
   }
}
在以下示例中,調(diào)用此迭代程序的 foreach 循環(huán)將執(zhí)行三次,每次都會(huì)按照前三個(gè) yield 語句指定的順序接收字符串:

list list = new list();
foreach(string s in list)
{
console.writeline(s);
}
如果要讓程序?qū)崿F(xiàn)迭代程序以遍歷列表中的元素,則需要使用 foreach 循環(huán)修改此迭代程序使其遍歷元素?cái)?shù)組,并在每次迭代中產(chǎn)生數(shù)組中的每個(gè)項(xiàng)目:

public class list
{
   internal object[] elements;
   internal int count;

   public object foreach()
   {
      foreach(object o in elements)
      {
         yield o;
      }
   }
}
迭代程序的工作原理
迭代程序代表所在的程序處理實(shí)現(xiàn)枚舉器模式的日常操作。c# 編譯器將您在迭代程序中編寫的代碼轉(zhuǎn)換成使用枚舉器模式的相應(yīng)類和代碼,而無需創(chuàng)建類和建立狀態(tài)機(jī)。通過這種方式,迭代程序顯著提高了開發(fā)人員的工作效率。

匿名方法
匿名方法是另一種實(shí)用的語言結(jié)構(gòu),它使程序員能夠創(chuàng)建可裝箱在委托中、并且可在以后執(zhí)行的代碼塊。它們基于稱作 λ 函數(shù)的語言概念,并且類似于 lisp 和 python 中的對(duì)應(yīng)語言概念。

創(chuàng)建委托代碼
委托是引用方法的對(duì)象。調(diào)用委托時(shí),將調(diào)用它所引用的方法。以下示例舉例說明了一個(gè)簡單的窗體,其中包含列表框、文本框和按鈕三個(gè)控件。初始化按鈕時(shí),程序?qū)⒅甘酒?click 委托引用該對(duì)象中其他位置存儲(chǔ)的 addclick 方法。在 addclick 方法中,文本框的值存儲(chǔ)在列表框中。由于 addclick 方法被添加到按鈕實(shí)例的 click 委托中,因此每次單擊該按鈕時(shí)都將調(diào)用此方法。

public class myform
{
   listbox listbox;
   textbox textbox;
   button button;

   public myform()
   {
listbox = new listbox(...);
textbox = new textbox(...);
button = new button(...);
button.click += new eventhandler(addclick);
}

   void addclick(object sender, eventargs e)
   {
      listbox.items.add(textbox.text);
   }
}
使用匿名方法
上一個(gè)示例非常直觀。其中創(chuàng)建了一個(gè)單獨(dú)的函數(shù),并對(duì)其進(jìn)行了委托引用,每當(dāng)調(diào)用此委托時(shí),程序都會(huì)調(diào)用該函數(shù)。在該函數(shù)中,執(zhí)行了一系列的可執(zhí)行步驟。使用匿名方法,程序無需為該類創(chuàng)建整個(gè)新方法,而可以直接引用委托中包含的可執(zhí)行步驟。匿名方法的聲明方法是先實(shí)例化一個(gè)委托,然后在實(shí)例化語句之后加上一對(duì)表示執(zhí)行范圍的花括號(hào),最后加上一個(gè)用于終止語句的分號(hào)。

在以下示例中,程序修改委托創(chuàng)建語句以直接修改列表框,而不是引用代表程序來修改該列表框的函數(shù)。存儲(chǔ)代碼的目的是為了修改委托創(chuàng)建語句之后的執(zhí)行范圍中的列表框。

public class myform
{
   listbox listbox;
   textbox textbox;
   button button;

   public myform()
   {
listbox = new listbox(...);
textbox = new textbox(...);
button = new button(...);
button.click += new eventhandler(sender, e)
{
         listbox.items.add(textbox.text);
};
}
}
請(qǐng)注意,“匿名”方法中的代碼是如何訪問和處理其執(zhí)行范圍以外聲明的變量的。實(shí)際上,匿名方法可以引用由類和參數(shù)聲明的變量,也可以引用所在方法聲明的局部變量。

向匿名方法傳遞參數(shù)
有趣的是,“匿名”方法語句包含兩個(gè)參數(shù),即 sender 和 e。查看 button 類的 click 委托的定義,您會(huì)發(fā)現(xiàn)委托引用的任何函數(shù)都必須包含兩個(gè)參數(shù),第一個(gè)參數(shù)為對(duì)象類型,第二個(gè)參數(shù)為 eventargs 類型。在第一個(gè)示例中,程序未使用“匿名”方法,而是向 addclick 方法傳遞了兩個(gè)參數(shù),類型分別為對(duì)象和 eventargs。

即使以內(nèi)聯(lián)方式編寫此代碼,委托仍必須接收兩個(gè)參數(shù)。在“匿名”方法中,必須聲明兩個(gè)參數(shù)的名稱,這樣關(guān)聯(lián)的代碼塊才能使用它們。當(dāng)觸發(fā)按鈕上的 click 事件時(shí),將調(diào)用“匿名”方法并將相應(yīng)的參數(shù)傳遞給該方法。

匿名方法的工作原理
遇到“匿名”委托時(shí),c# 編譯器會(huì)自動(dòng)將其執(zhí)行范圍內(nèi)的代碼轉(zhuǎn)換為唯一命名類中的唯一命名函數(shù)。然后將設(shè)置存儲(chǔ)代碼塊的委托,以引用編譯器生成的對(duì)象和方法。調(diào)用委托時(shí),將通過編譯器生成的方法執(zhí)行“匿名”方法塊。

局部類型
盡管在單個(gè)文件中維護(hù)類型的所有源代碼是面向?qū)ο缶幊痰暮梅椒ǎ袝r(shí)性能約束會(huì)使得類型變大。此外,在某些情況下將類型分割成子類型所耗費(fèi)的開銷是無法讓人接受的。而且,程序員經(jīng)常會(huì)創(chuàng)建或使用應(yīng)用程序來發(fā)布源代碼和修改結(jié)果代碼。遺憾的是,當(dāng)再次發(fā)布源代碼時(shí),所有現(xiàn)有的源代碼修改將被覆蓋。

局部類型允許您將包含大量源代碼的類型分割成多個(gè)不同的源文件,以便于開發(fā)和維護(hù)。此外,局部類型可用于將計(jì)算機(jī)生成的類型部分與用戶編寫的類型部分分隔開,從而更易于補(bǔ)充或修改工具生成的代碼。

在以下示例中,兩個(gè) c# 代碼文件 file1.cs 和 file2.cs 中都定義了名為 foo 的類。如果不使用局部類型,將會(huì)出現(xiàn)編譯錯(cuò)誤,因?yàn)檫@兩個(gè)類存在于同一個(gè)命名空間中。使用 partial 關(guān)鍵字,可以指示編譯器:別處可能包含此類的其他定義。

file1.cs file2.cs
public partial class foo
{
public void myfunction()
{
// 在此處執(zhí)行操作
}
}


public partial class foo
{
   public void myotherfunction()
   {
      // 在此處執(zhí)行操作
   }
}




編譯時(shí),c# 編譯器將收集局部類型的所有定義并將它們組合在一起。編譯器生成的結(jié)果 il 顯示了組合而成的單個(gè)類,而不是將多個(gè)類分別作為單獨(dú)的類進(jìn)行連續(xù)顯示。

符合標(biāo)準(zhǔn)
2001 年 12 月,歐洲計(jì)算機(jī)制造商協(xié)會(huì) (ecma) 將 c# 編程語言批準(zhǔn)為一項(xiàng)標(biāo)準(zhǔn) (ecma 334)。此后不久,c# 標(biāo)準(zhǔn)便得到國際標(biāo)準(zhǔn)化組織 (iso) 的快速跟蹤處理,預(yù)計(jì)很快就會(huì)得到批準(zhǔn)。c# 標(biāo)準(zhǔn)的創(chuàng)建是新編程語言發(fā)展史中的重要里程碑,它預(yù)示著未來有望在各種操作系統(tǒng)平臺(tái)上編寫多種實(shí)現(xiàn)。實(shí)際上,我們從其簡短的歷史中可以看到,許多第三方編譯器供應(yīng)商和研究人員已經(jīng)將它當(dāng)作標(biāo)準(zhǔn)來實(shí)現(xiàn)并創(chuàng)建了自己的 c# 編譯器版本。

microsoft 歡迎客戶對(duì)在 c# 語言中添加上面提到的功能提供反饋意見,并打算將這些功能提交給正在進(jìn)行的語言標(biāo)準(zhǔn)化進(jìn)程。

可用性
下面介紹的功能將在 c# 編譯器的未來版本中實(shí)現(xiàn)。2003 年年初,visual studio .net 的“everett”版本將包含為完全符合 ecma 標(biāo)準(zhǔn)而略作修改的 c# 版本。此版本不包含本文介紹的功能。microsoft 打算在 visual studio 的“vs for yukon”版本中包含這些功能,但具體的發(fā)布日期還未確定。

在接下來的幾個(gè)月中,microsoft 將發(fā)布有關(guān)這些功能的詳細(xì)信息,包括所有規(guī)范。歡迎廣大程序員和語言設(shè)計(jì)團(tuán)體就這些功能以及任何其他感興趣的語言功能提出自己的看法和反饋。您可以將電子郵件發(fā)送到 mailto:[email protected],與 c# 語言設(shè)計(jì)人員取得聯(lián)系。

更多信息
c# community web 站點(diǎn):http://www.csharp.net

visual c#(tm) product web 站點(diǎn):http://msdn.microsoft.com/vcsharp

  

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 会泽县| 襄城县| 崇仁县| 昭觉县| 清涧县| 隆化县| 随州市| 和田市| 澎湖县| 新泰市| 集贤县| 依兰县| 札达县| 陆河县| 宁国市| 滕州市| 宁安市| 鄯善县| 宁津县| 湾仔区| 浦县| 城步| 二连浩特市| 洪湖市| 环江| 贞丰县| 华宁县| 武定县| 鹤庆县| 龙里县| 平果县| 辉南县| 阿瓦提县| 平罗县| 成都市| 土默特右旗| 永年县| 即墨市| 唐河县| 宿松县| 兰考县|