亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

C#、Java以及C++的泛型

2024-07-21 02:26:57
字體:
來源:轉載
供稿:網友

摘要

anders hejlsberg,c#的主架構師,與bruce eckel和bill venners 談論了c#和java的泛型、c++模板、c#的constraints特性以及弱類型化和強類型化的問題。

anders hejlsberg,微軟的一位杰出工程師,他領導了c#(發音是c sharp)編程語言的設計團隊。hejlsberg首次躍上軟件業界舞臺是源于他在80年代早期為ms-dos和cp/m寫的一個pascal編譯器。不久一個叫做borland的非常年輕的公司雇傭了他并且買下了他的編譯器,從那以后這個編譯器就作為turbo pascal在市場上推廣。在borland,hejlsberg繼續開發turbo pacal并且在后來領導一個團隊設計turbo pascal的替代品:delphi。1996年,在borland工作13年以后,hejlsberg加入了微軟,在那里一開始作為visual j++和windows基礎類庫(wfc)的架構師。隨后,hejlsberg擔任了c#的主要設計者和.net框架創建過程中的一個主要參與者?,F在,anders hejlsberg領導c#編程語言的后續開發。

2003年7月30號,bruce eckel(《thinking in c++》以及《thinking in java》的作者)和bill venners(artima.com的主編)與anders hejlsberg在他位于華盛頓州redmond的微軟辦公室進行了一次面談。這次訪談的內容將分多次發布在artima.com以及bruce eckel將于今年秋天發布的一張音頻光碟上。在這次訪談中,anders hejlsberg談論了c#語言和.net框架設計上的一些取舍。

·        在 第一部分:c#的設計過程中, hejlsberg談論了c#設計團隊所采用的流程,以及在語言設計中可用性研究(usability studies)和好的品味(good taste)相對而言的優點。

·        在第二部分:checked exceptions的問題中, hejlsberg談論了已檢測異常(checked exceptions)的版本(versionability)問題和規模擴展(scalability)問題。

·        在第三部分: 委托、組件以及表面上的簡單性里,hejlsberg 談論了委托(delegates)以及c#對于組件的概念給予的頭等待遇。

·        在第四部分:版本,虛函數和覆寫里,hejlsberg解釋了談論了為什么c#的方法默認是非虛函數,以及為什么程序員必須顯式指定覆寫(override)。

在第五部分:契約和互操作性里,hejlsberg談論了dll hell、接口契約、strong anmes以及互操作的重要性。
在第六部分:inappropriate abstractions里, hejlsberg以及c#團隊的其他成員談論了試圖讓網絡透明的分布式系統,以及試圖屏蔽掉數據庫的對象——關系映射。  
在第七部分, hejlsberg比較了c#和java的泛型以及c++模板的實現方法,并且介紹了c#的constraints特性以及弱類型化和強類型化的問題。
泛型概述
bruce eckel: 能否就泛型做一個簡短的介紹?

anders hejlsberg: 泛型的本質就是讓你的類型能夠擁有類型參數。它們也被成為參數化類型(parameterized types)或者參數的多態(parametric polymorphism)。經典的例子十九一個list集合類。list是一個方便易用的、可增長的數組。它有一個排序方法,你可以通過索引來引用它的元素,等等。現今,如果沒有參數化類型,在使用數組或者lists之間就會有些別扭的地方。如果使用數組,你得到了強類型保證,因為你可以定義一個關于customer的數組,但是你沒有可增長性和那些方便易用的方法。如果你用的是list,雖然你得到了所有這些方便,但是卻喪失了強類型保證。你不能指定一個list是關于什么的list。它只是一個關于object的list。這會給你帶來一些問題。類型檢測必須在運行時刻做,也就意味著沒有在編譯時刻對類型進行檢測。即便是你塞給list一個customer對象然后試圖取出一個string,編譯器也不會有絲毫的抱怨。直到運行時刻你才會發現他會出問題。另外,當把基元類型(primitive type)放入list的時候,還必須對它們進行裝箱(box)?;谏鲜鏊羞@些問題,lists與arrays之間的這種不和諧的地方總是存在的。到底選擇哪個,會讓你一直猶豫不決。

泛型的最大好處就是它讓你有了一個兩全其美的辦法(you can have your cake and eat it too),因為你可以定義一個list<t>[讀作:list of t]。當使用一個list的時候,你可以實實在在地知道這個list是關于什么類型的list,并且讓編譯器為你做強類型檢測。這只是它最直接的好處。接下來還有其它各種各樣的好處。當然,你不會僅僅想讓list擁有泛型。哈希表(hashtable)或者字典(dictionary)——隨便你怎么叫它——把鍵(keys)映射到值(values)。你可能會想要把strings映射到customrs,或者ints到orders,而且是以強類型化的方式。

c#的泛型
bill venners: 泛型在c#中是如何工作的?

anders hejlsberg: 沒有泛型的c#,基本上你只能寫class list {...}。有了泛型,你可以寫成class list<t> {...},這里t是類型參數。在list<t>范圍內你可以把t當作類型來使用,當真正需要創建一個list對象的時候,寫成list<int>或者list<customer>。新類型是通過list<t>構建的,實際上就像是你的類型參數替換掉了原本的類型參數。所有的t都變成了ints或者customers,你不需要做類型轉換,因為到處都會做強類型檢驗。

在clr(common language runtime)環境下,當編譯list<t>或者其它任何generic類型的時候,會像其它普通類型一樣,先編譯成中間語言il(intermediate language)以及元數據。理所當然,il以及元數據包含了額外的信息,從而可以知道有一個類型參數,但是從原則上來說,generic類型的編譯與其它類型并沒有什么不同。在運行時刻,當應用程序第一次引用到list<int>的時候,系統會查找看是否有人已經請求過list<int>。如果沒有,它會把list<t>的il和元數據以及類型參數int傳遞給jit。而jiter在即時編譯il的過程中,也會替換掉類型參數。

bruce eckel: 也就是說它是在運行時刻實例化的。

anders hejlsberg: 的確如此,它是在運行時刻實例化的。它在需要的時候產生出針對特定類型的原生代碼(native code)。從字面上看,當你說list<int>的時候,你會得到一個關于int的list。如果generic類型的代碼使用了一個關于t的array,你得到的就是一個關于int的array。

bruce eckel: 垃圾回收機制會在某個時候來回收它么?

anders hejlsberg: 可以說會,也可以說不會,這是一個正交的問題。這個類在應用程序范圍內被創建,然后在這個應用程序范圍內就一直存在下去。如果你殺掉這個應用程序,那么這個類也就消失了,這點跟其它類一樣。

bruce eckel: 如果我有一個應用程序用到了list<int>和list<cat>,但是它從來沒有走到使用list<cat>的那個分支。。。。。。

anders hejlsberg:。。。。。。那么系統就不會實例化一個list<cat>。現在讓我說說一些例外的情況。如果你是使用ngen在創建一個影像(image),也就是說你在直接產生一個native的映像,你可以提早產生這些實例。但是如果你是在通常的情況下運行程序,是否實例化是完全根據需要來確定的,而且推遲到越晚越好。

這之后,我們針對所有值類型(比如list<int>,list<long>,list<double>, list<float>)的實例化做進一步的處理,創建可執行的原生代碼的唯一拷貝。這樣list<int>就有它自己的代碼。list<long>也有它自己的代碼。list<float>也是如此。對于所有引用類型(reference types),我們共享這些代碼,因為它們所代表的東西是相同的。它們只是一些指針罷了。

bruce eckel: 你需要進行類型轉換吧。

anders hejlsberg: 不,實際上并不需要。我們可以共享native image,但實際上它們有各自單獨的虛函數表(vtables)。我只是想指出,當共享代碼有意義的時候,我們會不遺余力的去做這件事情,但是當你非常需要運行效率的時候,我們對于共享代碼會非常謹慎。通常對于值類型,你確實會關心list<int>元素的類型就是int。你不想把它們裝箱(box)成objects。對值類型進行裝箱/拆箱,是可以用來進行代碼共享的一種方法,但是這種方法代價過于昂貴。

bill venners: 對于引用類型,實際上也是完全不同的類。list<elephant>和list<orangutan>是不同的,但是它們確實共享所有的類方法的代碼。

anders hejlsberg: 是的。作為實現上的細節來說,它們確實共享了相同的原生代碼(native code)。

c#泛型與java泛型的比較
bruce eckel: c#泛型相比java泛型有什么特點?

anders hejlsberg: java的泛型實現是基于一個最初叫做pizza的項目,這個項目是由martin odersky和其他一些人完成的。pizza被重新命名為gj,然后他成了一個jsr,并且最后被采納進了java語言。這個特定的泛型proposal有一個關鍵的設計目標,就是它應該能夠跑在不必經過改動的虛擬機上。不用改動虛擬機當然很棒,但是它也帶來了一系列奇奇怪怪的限制。這些限制并不都是顯而易見的,但是很快你就會說,“hmm,這可有點怪?!?/font>

比如說,使用java泛型,實際上你就得不到任何剛才我所說得程序執行上的效率,因為當你在java里編譯一個泛型類的時候,編譯器拿掉了類型參數并到處代之以object。list<t>編譯好的影像文件(image)就像是一個到處使用object(作為類型參數)的list。當然,如果你試圖創建一個list<int>,那就的對所有用到的int對象進行裝箱(boxing)。這就產生了很大的負擔。此外,為了與老的虛擬機兼容,編譯器實際上會插入各種各樣的轉換代碼,而這些轉換代碼并不是由你來寫的。如果是一個關于object的list,而你試圖把這些objects當作customers來對待,這些objects必須在某些地方被轉換成customers,以便讓verifier的驗證能夠通過。實際上它們的實現所做的就是自動為你插入那些類型轉換。也就是說你得到了語法上的甜頭,或者至少是一部分語法上的甜頭,但是你并沒有得到任何程序執行上的效率。這是我認為java泛型解決方案的第一個問題。

第二個問題是,我認為這可能是更大的一個問題,因為java的泛型實現依賴于去處掉類型參數,當到了運行時刻,你實際上并沒有一個相對于運行時刻的可靠的泛型表示。當你在java里針對一個泛型list使用反射(reflection)的時候,你并不知道這個list到底是關于什么的list。它只是一個list。因為你已經丟失了類型信息,對于任何動態代碼生成(dynamic code-generation)的應用或者基于反射的應用,就沒法工作了。這種趨勢對我來說已經很明了了,(丟失類型信息的)情況越來越多。它根本沒辦法工作,因為你丟失了類型信息。而在我們的實現里,所有這些信息都是可獲得的。你可以通過反射得到list<t>對象的system.type表示。但這時候你還不能創建它的實例,因為你還不知道t是什么。但是你可以使用反射得到int的system.type表示。然后你可以請求反射機制把這兩個東西放在一起創建一個list<int>,這樣你就得到了另外一個用以表示list<int>的system.type。也就是說,從表示方法來說,任何你可以在編譯時刻做到的事情,你也可以在運行時刻做到。

c#泛型與c++模板的比較
bruce eckel: c#泛型相比c++模板有哪些特點?

anders hejlsberg: 在我看來,理解c#泛型與c++模板之間的差異最重要的一點就是:c#泛型實際上就像是類,除了它們有類型參數。而c++模板實際上就像是宏(macros),除了它們看起來像是類。

c#泛型與c++模板最大的不同之處在于類型檢驗發生的時間以及實例化的方式。首先,c#是在運行時刻實例化的,而c++ 是在編譯時刻或者可能是在link的時候。但是不管怎樣,c++模板實例化發生在程序運行之前。這是第一個不同之處。第二個不同之處在于,當你編譯generic類型的時候,c#對它進行強類型檢驗。對于像list<t>這樣未加限制的類型參數(unconstrained type parameter),類型t的值所能使用的方法僅限于object類型所包含的方法,因為只有這些方法才是通常我們保證能夠存在的方法。也就是說,在c#泛型里,我們保證你所實施于類型參數的任何操作都會成功。

c++正好與此相反。在c++里,你可以對一個類型參數做任何你想做的事情。但是當你對它進行實例化的時候,它有可能通不過,而你會得到一些非常難懂的錯誤信息。比如,你有一個類型參數t以及兩個t類型的變量,x和y,如果你寫成x+y,那你最好事先定義了用于兩個t型變量相加的+運算符,否則你會得到一些古怪的錯誤信息。所以從某種意義上說,c++模板實際上是非類型化的,或者說是弱類型化的。而c#泛型則是強類型化的。

c#泛型的constraints特性
bruce eckel: constraints在c#泛型里是如何工作的?

anders hejlsberg: 在c#泛型里,我們可以針對類型參數加一些限制條件(constraints)。還以list<t>為例,你可以寫成,class list<t> where t: icomparable。意思是t必須實現icomparable接口。

bruce eckel: 有意思的是在c++里限制條件是隱含的。

anders hejlsberg: 是的。在c#里,你也可以讓限制條件是隱含的。比如說我們有一個dictionary<k,v>,它有一個add方法,以k為鍵(key)v為值(value)。add方法的實現很可能需要把傳入的鍵與dictionary已有的鍵進行比較,而且它可能通過一個叫做icomparable的接口來做這個比較。一種方法是把key參數轉換成icomparable,然后調用compareto方法。當然,當你這么做的時候,你就已經針對k類型和key參數創建了一個隱式的限制條件。如果傳入的key沒有實現icomparable接口,你就會得到一個運行時錯誤。但是實際上你并沒有在你的哪個方法里或者約定里明確表明key必須實現icomparable。而且你當然還得付出運行時刻類型檢測的代價,因為實際上你所做的是運行時刻的動態類型檢驗。

使用constraint,你可以把代碼里的動態檢驗提前,在編譯時刻或者加載的時候對它進行驗證。當你指定k必須實現icomparable,這就隱含了一系列的東西。對于任何k類型的值,你都可以直接訪問接口方法,而不需要進行轉換,因為從語義上來說,在整個程序里k類型要實現這個接口,這一點是得到保證的。無論什么時候你想要創建該類型的一個實例,編譯器都會針對你給出的任何作為k參數的類型進行檢驗,看它是否實現了icomparable。如果沒有實現,你會得到一個編譯時錯誤。或者如果你是利用反射來做的話,會得到一個異常。

bruce eckel: 你說到了編譯器以及運行時刻。

anders hejlsberg: 編譯器會做檢驗,但是你也可能是在運行時刻通過反射來做的,這時候就由系統來做檢驗。如前所述,任何你在編譯時刻可以做的事情,你都可以在運行時刻通過反射來做。

bruce eckel: 我是否可以寫一個模板函數,或者換句話說,一個參數類型未知的函數?你們是在所做的是給容器加上更強的類型檢驗,但是我是否可以像在c++模板里那樣得到弱類型化的東西呢?比如說,我是否可以寫一個函數,它以a a和b b作為參數,然后我在代碼里就可以寫a+b?我是否可以不關心a和b是什么,只要它們有一個“+”運算符就可以了,因為我想要的是弱類型化。

anders hejlsberg: 你實際上問的是,通過constraints你到底能做到什么程度?與其它特性類似,如果把constraints發揮到極致,他可以變得異常復雜。仔細想想,其實constraints是一種模式匹配(pattern matching)的機制。你想要能指定,“該類型參數必須有一個接受兩個參數的構造函數,并且實現了+運算符,要有某個靜態方法,以及其它兩個非靜態方法,等等?!眴栴}是,你想要這種模式匹配的機制復雜到哪種程度?

從什么也不做到功能全面的模式匹配,這是很大的一個范圍。我們認為什么也不做太說不過去了,而全面的模式匹配又會變得非常復雜,所以我們選擇了折衷的方式。我們允許你指定一個constraint,它可以是一個類、零個或者多個接口、以及叫做constructor constraint的東西。比如說,你可以指定“該類型必須實現ifoo和ibar接口,”或者“該類型必須繼承自基類x?!币坏┠氵@么做了,我們會在所有地方做類型檢驗以確認該constraint是否為真,包括編譯時刻和運行時刻。任何由這個constraint所暗含的方法都可以通過類型參數的實例直接訪問。

另外,在c#里,運算符都是靜態成員函數。也就是說,一個運算符永遠不可能成為一個接口的成員函數,因此一個接口限制條件(interface constraint)永遠不可能讓你指定一個“+”運算符。要指定一個“+”運算符,唯一的方法就是通過一個類限制條件(class constraint),這個類限制條件指定說必須繼承自某個類,比如說number類,因為number有一個“+”運算符。但是你不可能把它抽象成:“必須有一個+運算符”,然后由我們來以多態的方式解析它的實際含義。

bill venners: 你是通過類型,而不是簽名(signature)來實現限制條件的。

anders hejlsberg: 是的。

bill venners: 也就是說指定類型必須擴展某個類或者實現某些接口。

anders hejlsberg: 是的。本來我們可以走得更遠。我們確實考慮過走得更遠一些,但是那會非常復雜。并且我們不知道添加這些復雜性相對于你所獲得的微不足道的好處,是否值得。如果你想做的事情沒有被constraint系統直接支持,你可以借助于工廠模式(factory pattern)來完成。比如說,你有一個矩陣類matrix<t>,在這個matrix里你想定義一個標量積(dot product)方法。這當然意味著你最終需要理解如何把兩個t相乘,但你不能把它表達成一個constraint,至少如果t是int、double或者float的時候這樣做不行。但是你可以這么做:讓matrix接受一個calculator<t>這樣的參數,然后在calculator<t>里聲明一個叫做multiply的方法。你實現這個方法并把它傳給matrix。

bruce eckel: calculator也是個參數化類型。

anders hejlsberg: 是的,它有點像factory模式??傊?,是有辦法來做這些事情的。可能不如你想要的那么棒,但是任何事情都是有代價的。

bruce eckel: 嗯,我感覺c++模板像是一種弱類型化(weak typing)的機制。當你開始在它上面添加constraints的時候,你是在從弱類型化轉向強類型化(strong typing)。通常加入強類型化都會讓事情更加復雜。這像是一個頻譜。

anders hejlsberg: 你所意識到的類型化(typing)的問題,其實是一個撥盤(dial)。你把它撥的越高,程序員越覺得難受,但同時代碼更安全了。但是在兩個方向上你都有可能把它撥過頭。

 

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
97在线精品视频| 国产日韩一区在线| 欧美肥婆姓交大片| 久久精品精品电影网| 国产精品日日摸夜夜添夜夜av| 51ⅴ精品国产91久久久久久| 在线观看日韩www视频免费| 日产精品久久久一区二区福利| 亚洲精品乱码久久久久久按摩观| 亚洲精品欧美极品| 精品国内产的精品视频在线观看| 国产视频福利一区| 国产精品极品尤物在线观看| 亚洲qvod图片区电影| 亚洲成人性视频| 亚洲图片在区色| 国产精品va在线播放| 国产精品视频地址| 欧美成人在线网站| 搡老女人一区二区三区视频tv| 精品久久久久久亚洲精品| 欧美福利视频在线| 国产精品成av人在线视午夜片| 欧美精品在线观看| 亚洲国产精品视频在线观看| 日韩电视剧在线观看免费网站| 中文字幕亚洲精品| 日韩在线不卡视频| 亚洲精品网站在线播放gif| 欧美区在线播放| 亚洲人成毛片在线播放| 精品小视频在线| 色琪琪综合男人的天堂aⅴ视频| 亚洲社区在线观看| 日韩在线观看免费网站| 欧美巨猛xxxx猛交黑人97人| 欧美激情一级欧美精品| 综合av色偷偷网| 日韩亚洲综合在线| 5566成人精品视频免费| 中文字幕日韩欧美精品在线观看| 久久精视频免费在线久久完整在线看| 日韩在线小视频| 亚洲国产黄色片| 日韩精品www| 亚洲第一精品夜夜躁人人爽| 91香蕉嫩草影院入口| www.欧美视频| 国产精品r级在线| 亚洲欧洲国产精品| 欧美日韩美女在线| 清纯唯美亚洲综合| 国产午夜精品一区二区三区| 欧美日韩国产精品专区| 欧美激情小视频| 九九热这里只有精品免费看| 亚洲欧美999| 伊人久久久久久久久久久| 国产丝袜一区二区三区免费视频| 亚洲伊人久久综合| 亚洲美女精品成人在线视频| 日本不卡高字幕在线2019| 国产精品视频精品视频| 午夜精品久久久久久久白皮肤| 国产一区二区免费| 日韩欧美主播在线| 亚洲xxxx3d| 91色在线观看| 欧美老妇交乱视频| 福利精品视频在线| 在线观看国产精品日韩av| 欧美黄色性视频| 欧美亚洲国产另类| 欧美一区三区三区高中清蜜桃| 国产精品视频公开费视频| 欧美成人精品一区| 日韩在线精品一区| 国产一区二区在线免费| 92国产精品久久久久首页| 国产精品久久久久久久久久三级| 欧美午夜女人视频在线| 久久99久久99精品中文字幕| 在线电影欧美日韩一区二区私密| 欧美最顶级的aⅴ艳星| 亚洲片在线观看| 国产91色在线免费| 亚洲人午夜精品| 欧美亚洲成人精品| 国产精品日韩电影| 在线精品视频视频中文字幕| 亚洲成人精品av| 国产精品第七影院| 欧美亚洲在线视频| 91精品国产高清| 亚洲欧美国产日韩天堂区| 福利视频一区二区| 国产精品久久久久久婷婷天堂| 国产欧美va欧美va香蕉在线| 精品毛片三在线观看| 亚洲人成在线观看网站高清| 55夜色66夜色国产精品视频| 久久精品久久久久久国产 免费| 日韩精品中文字幕在线播放| 亚洲男人天堂网| 亚洲aaa激情| 久久久久免费视频| 亚洲激情在线观看视频免费| zzijzzij亚洲日本成熟少妇| 国产成人精彩在线视频九色| 国产成人精品国内自产拍免费看| 在线日韩中文字幕| 伊人青青综合网站| 亚洲国产高清高潮精品美女| 亚洲电影中文字幕| 国产福利视频一区二区| 久久亚洲春色中文字幕| 精品呦交小u女在线| 亚洲天堂网站在线观看视频| 欧美亚洲激情视频| 欧美成人免费小视频| 97在线视频免费看| 中文字幕av一区二区三区谷原希美| 欧美日韩国产在线看| 亚洲福利在线视频| 久久久久久91香蕉国产| 亚洲视频在线观看视频| 亚洲美女免费精品视频在线观看| 日韩精品在线免费观看| 中文字幕欧美日韩| 国产精品久久久久久久久久三级| 日韩精品在线影院| 久久在精品线影院精品国产| 91地址最新发布| 中文字幕亚洲欧美一区二区三区| 91性高湖久久久久久久久_久久99| 欧美亚洲免费电影| 亚洲欧美在线磁力| 亚洲性xxxx| 日韩国产一区三区| 最近免费中文字幕视频2019| 国产一区二区三区在线看| 蜜臀久久99精品久久久久久宅男| 一区二区中文字幕| 国产综合久久久久久| 欧美性生交xxxxxdddd| 视频在线一区二区| 国产成人一区二区三区| 色悠悠久久久久| 欧美电影在线观看网站| 国产精品成人va在线观看| 91亚洲精品久久久| 久久综合国产精品台湾中文娱乐网| 色综合久综合久久综合久鬼88| 亚洲剧情一区二区| 日韩在线激情视频| 91精品视频专区| 91国产视频在线播放| 国产成人一区二区三区电影| 精品国产一区二区三区久久| 国产精品高潮呻吟久久av无限| 国产亚洲美女精品久久久| 日韩免费在线免费观看| 97超碰色婷婷| 日韩欧美黄色动漫|