c,c++,c#,java?這些有什麼區別?java
C語言:linux
目前最著名、最有影響、應用最普遍的windows、linux和UNIX三個操做系統都是用C語言編寫的。0S是計算機系統(由軟硬件兩個子系統構成)的核心和靈魂,它是軟件中最龐大最複雜的系統軟件。既然如此龐大複雜的0S均可以用c語言編寫,從狹義而言,還有什麼系統軟件和應用軟件不能用c語言編寫呢?由此能夠確定的說,c語言是一門十分優秀而又重要的語言。c++
c語言程序設計是過程性程序設計語言,它的發展貫穿了計算機發展的歷程,它蘊含了程序設計的基本思想,囊括了程序設計的基本概念,因此它是理工科高等院校的一門基礎課程。算法
從市面上有關c語言的書籍和高等院校採用的教材來看,它們有一個共性,那就是:脫離了實際應用(全是小打小鬧的小例子),純粹的過程性程序設計,沒有軟件工程思想的體現,沒有必定程序設計風格,僅僅是爲了讓你們明白什麼是c語言而已。編程
高等院校開設c語言程序設計的目的是讓學生對程序設計有個入門,有個直觀的理解,同時爲其餘後續課程做鋪墊。c#
C++:windows
C++語言是在C語言的基礎是擴展而成的.因此兩種語言的基本語法和語義是相同。C++中加入了面向對程序設計(OOP)的特徵。數組
下面的三個主要性質刻劃OOP語言的特色:安全
封裝性:把一個數據結構同操做的函數(行爲或方法)組合在一塊兒。封裝性是藉助於一種新的結構和數據類型機制——類實現的。網絡
繼承性:創建一個新的派生類,它從一個或多個先前定義的基類中繼承函數和數據,並且可能從新定義或加進新的數據行爲,這樣就創建了類的層次。
多態性:給行爲取一個名字或符號,它共享一個類的層次,在這個層次中的每一個類都以適合本身的方式實現這個行爲。
C#:
C#(讀作 "C sharp",中文譯音「夏普」)是微軟公司發佈的一種面向對象的、運行於.NET Framework之上的高級程序設計語言,並定於在微軟職業開發者論壇(PDC)上登臺亮相.C#是微軟公司研究員Anders Hejlsberg的最新成果.C#看起來與Java有着驚人的類似;它包括了諸如單一繼承,界面,與Java幾乎一樣的語法,和編譯成中間代碼再運行的過程.可是C#與Java有着明顯的不一樣,它借鑑了Delphi的一個特色,與COM(組件對象模型)是直接集成的,並且它是微軟公司.NET windows網絡框架的主角.
Java:
Java是一種能夠編寫跨平臺應用軟件的面向對象的程序設計語言,由昇陽(太陽微電子,Sun Microsystems)公司的James Gosling等人於1990年代初開發的.具備如下特徵的高級程序語言:
簡單面向對象可分佈可解釋強壯安全性結構化輕便功能強大多線程動態...
Java既能夠被編譯,也能夠被解釋。經過編譯器,能夠把Java程序翻譯成一種中間代碼 -稱爲字節碼 -能夠被Java解釋器解釋的獨立於平臺的代碼。經過解釋器,每條Java字節指令被分析,而後在計算機上運行。只需編譯一次,程序運行時解釋執行。
C語言與VC++的區別有不少:
1,全新的程序程序思惟,C語言是面向過程的,而VC++是面向對象的。
2,C語言有標準的函數庫,它們鬆散的,只是把功能相同的函數放在一個頭文件中;而VC++對於大多數的函數都是有集成的很緊密,特別是C語言中沒有的VC++6.0中的API是對Window系統的大多數API有機的組合,是一個集體。但你也可能單獨調用API。
3,特別是VC++中的圖形處理,它和語言的圖形有很大的區別。C語言中的圖形處理函數基本上是不能用在中VC++中的。主持人注:C語言標準中不包括圖形處理。這裏的C語言的圖形處理指的是DOS下的C語言。
4,C和VC++中都有結構的概念,可是在C語言中結構只有成員變量,而沒成員方法,而在VC++中結構中,它能夠有本身的成員變量和成員函數。可是在C語言中結構的成員是公共的,什麼想訪問它的均可以訪問;而在VC++中它沒有加限定符的爲私有的。
4,C語言能夠寫不少方面的程序,可是VC++能夠寫得更多更好,VC++能夠寫基於DOSr程序,寫DLL,寫控件,寫系統。
5,C語言對程序的文件的組織是鬆散的,幾乎是全要程序處理;而vc++對文件的組織是以工程,各文件分類明確。
6,VC++中的IDE很智能,和VB同樣,有的功能可能比VB還強。
7,VC++對能夠自動生成你想要的程序結構使你能夠省了不少時間。有不少可用的工具如加入MFC中的類的時候,加入變量的時候等等。
8,VC++中的附加工具也有不少,能夠進行系統的分析,能夠查看API;能夠查看控件。
9,調試功能強大,而且方法多樣。
首先我先回答你關於「面向對象」和「面向過程」的區別。
他們主要是編程的思想的不一樣。。。
舉個例子:好比你想作一個模型飛機,利用「面向過程」的思想,你所想的就是,先作頭再作身體,再作尾巴。。它是一個比較順着的概念。而若是利用「面向對象」的思想,你所想的就是,你要作飛機的話,它有翅膀,頭部,身體,尾巴等各個部件,你先把各個部分作好,再考慮他們的直接的接口怎麼連。。。這就是區別。你能夠發現「面向對象」的優點。
再就是C,C++,C#的問題。。因爲我是先學的C語言再學的C++,因此,個人想法就是,光是從C語言和C++這個方向上說的話,而不從他們的編程程序VC6.0以及turboC來講,C++是在C語言的思想上引入了關鍵性的「類(class)」的問題。而從編程的整體思想上即算法上區別不大。因此,我建議你先把C語言學好,學通。。再去學C++,最後學VC++。學C語言主要學算法,C++則主要掌握關於類,封裝,虛函數,繼承等。。再去學VC++,必定不能亂了順序,又或者學的不精就轉下一個,否則。。。你就知道什麼真正的叫「困難」了。。
C#與Java的比較
C#(C-Sharp)是Microsoft的新編程語言,被譽爲「C/C++家族中第一種面向組件的語言」。然而,無論它本身宣稱的是什麼,許多人認爲C#更像是Java的一種克隆,或者是Microsoft用來替代Java的產品。事實是不是這樣的呢?
本文的比較結果代表,C#不止是Java的同胞那麼簡單。若是你是一個Java開發者,想要學習C#或者瞭解更多有關C#的知識,那麼本文就是你必須把最初10分鐘投入於其中的所在。
C#的語言規範由Microsoft的Anders Hejlsberg與Scott Wiltamuth編寫。在當前Microsoft天花亂墜的宣傳中,對C#和C++、Java做一番比較老是頗有趣的。考慮到當前IT媒體的輿論傾向,若是你早就知道C#更接近Java而不是C++,事情也不值得大驚小怪。對於剛剛加入這場討論的讀者,下面的表1讓你本身做出判斷。顯然,結論應該是:Java和C#雖然不是孿生子,但C#最主要的特點卻更接近Java而不是C++。
瞭解表1總結的重要語言功能以後,請繼續往下閱讀,瞭解C#和Java的一些重要區別。
簡單數據類型(Primitive)在C#中稱爲值類型,C#預約義的簡單數據類型比Java多。例如,C#有unit,即無符號整數。表2列出了全部C#的預約義數據類型:
2.二、常量
忘掉Java中的static final修飾符。在C#中,常量能夠用const關鍵詞聲明。
1 public const int x = 55;
此外,C#的設計者還增長了readonly關鍵詞。若是編譯器編譯時未能肯定常量值,你可使用readonly關鍵詞。readonly域只能經過初始化器或類的構造函數設置。
2.三、公用類的入口點
在Java中,公用類的入口點是一個名爲main的公用靜態方法。main方法的參數是String對象數組,它沒有返回值。在C#中,main方法變成了公用靜態方法Main(大寫的M),Main方法的參數也是一個String對象數組,並且也沒有返回值,以下面的原型聲明所示:
public static void Main(String[] args)
可是,C#的Main方法不侷限於此。若是不向Main方法傳遞任何參數,你可使用上述Main方法的一個重載版本,即不帶參數列表的版本。也就是說,下面的Main方法也是一個合法的入口點:
public static void Main()
另外,若是你認爲有必要的話,Main方法還能夠返回一個int。例如,下面代碼中的Main方法返回1:
1 using System; 2 public class Hello { 3 public static int Main() { 4 Console.WriteLine("Done"); 5 return 1; 6 }
與此相對,在Java中重載main方法是不合法的。
2.四、switch語句
在Java中,switch語句只能處理整數。但C#中的switch語句不一樣,它還可以處理字符變量。請考慮下面用switch語句處理字符串變量的C#代碼:
1 using System; 2 public class Hello { 3 public static void Main(String[] args) { 4 switch (args[0]) { 5 case "老闆": 6 Console.WriteLine("早上好!咱們隨時準備爲您效勞!"); 7 break; 8 case "僱員": 9 Console.WriteLine("早上好!你能夠開始工做了!"); 10 break; 11 default: 12 Console.WriteLine("早上好!祝你好運!"); 13 break; 14 } 15 } 16 }
與Java中的switch不一樣,C#的switch語句要求每個case塊或者在塊的末尾提供一個break語句,或者用goto轉到switch內的其餘case標籤。
2.五、foreach語句
foreach語句枚舉集合中的各個元素,爲集合中的每個元素執行一次代碼塊。請參見下面的例子。
1 using System; 2 public class Hello { 3 public static void Main(String[] args) { 4 foreach (String arg in args) 5 Console.WriteLine(arg); 6 } 7 }
若是在運行這個執行文件的時候指定了參數,好比「Hello Peter Kevin Richard」,則程序的輸出將是下面幾行文字:
1 Peter 2 Kevin 3 Richard
2.六、C#沒有>>>移位操做符
C#支持uint和ulong之類的無符號變量類型。所以,在C#中,右移操做符(即「>>」)對於無符號變量類型和帶符號變量類型(好比int和long)的處理方式不一樣。右移uint和ulong丟棄低位並把空出的高位設置爲零;但對於int和long類型的變量,「>>」操做符丟棄低位,同時,只有當變量值是正數時,「>>」才把空出的高位設置成零;若是「>>」操做的是一個負數,空出的高位被設置成爲1。
Java中不存在無符號的變量類型。所以,咱們用「>>>」操做符在右移時引入負號位;不然,使用「>>」操做符。
2.七、goto關鍵詞
Java不用goto關鍵詞。在C#中,goto容許你轉到指定的標籤。不過,C#以特別謹慎的態度對待goto,好比它不容許goto轉入到語句塊的內部。在Java中,你能夠用帶標籤的語句加上break或continue取代C#中的goto。
2.八、聲明數組
在Java中,數組的聲明方法很是靈活,實際上有許多種聲明方法都屬於合法的方法。例如,下面的幾行代碼是等價的:
1 int[] x = { 0, 1, 2, 3 }; 2 int x[] = { 0, 1, 2, 3 };
但在C#中,只有第一行代碼合法,[]不能放到變量名字以後。
2.九、包
在C#中,包(Package)被稱爲名稱空間。把名稱空間引入C#程序的關鍵詞是「using」。例如,「using System;」這個語句引入了System名稱空間。
然而,與Java不一樣的是,C#容許爲名稱空間或者名稱空間中的類指定別名:
1 using TheConsole = System.Console; 2 public class Hello { 3 public static void Main() { 4 TheConsole.WriteLine("使用別名"); 5 } 6 }
雖然從概念上看,Java的包相似於.NET的名稱空間。然而,二者的實現方式不一樣。在Java中,包的名字同時也是實際存在的實體,它決定了放置.java文件的目錄結構。在C#中,物理的包和邏輯的名稱之間是徹底分離的,也就是說,名稱空間的名字不會對物理的打包方式產生任何影響。在C#中,每個源代碼文件能夠從屬於多個名稱空間,並且它能夠容納多個公共類。
.NET中包的實體稱爲程序集(Assembly)。每個程序集包含一個manifest結構。manifest列舉程序集所包含的文件,控制哪些類型和資源被顯露到程序集以外,並把對這些類型和資源的引用映射到包含這些類型與資源的文件。程序集是自包含的,一個程序集能夠放置到單一的文件以內,也能夠分割成多個文件。.NET的這種封裝機制解決了DLL文件所面臨的問題,即臭名昭著的DLL Hell問題。
2.十、默認包
在Java中,java.lang包是默認的包,它無需顯式導入就已經自動包含。例如,要把一些文本輸出到控制檯,你可使用下面的代碼:
1 System.out.println("Hello world from Java");
C#中不存在默認的包。若是要向控制檯輸出文本,你使用System名稱空間Console對象的WriteLine方法。可是,你必須顯式導入全部的類。代碼以下:
1 using System; 2 public class Hello { 3 public static void Main() { 4 Console.WriteLine("Hello world from C#"); 5 } 6 }
2.十一、面向對象
Java和C#都是徹底面向對象的語言。在面向對象編程的三大原則方面,這兩種語言接近得不能再接近。
繼承:這兩種語言都支持類的單一繼承,但類能夠實現多個接口。全部類都從一個公共的基類繼承。
封裝與可見性:不管是在Java仍是C#中,你均可以決定類成員是否可見。除了C#的internal訪問修飾符以外,二者的可見性機制很是類似。
多態性:Java和C#都支持某些形式的多態性機制,且二者實現方法很是相似。
2.十二、可訪問性
類的每一個成員都有特定類型的可訪問性。C#中的訪問修飾符與Java中的基本對應,但多出了一個internal。簡而言之,C#有5種類型的可訪問性,以下所示:
public:成員能夠從任何代碼訪問。
protected:成員只能從派生類訪問。
internal:成員只能從同一程序集的內部訪問。
protected internal:成員只能從同一程序集內的派生類訪問。
private:成員只能在當前類的內部訪問。
2.1三、派生類
在Java中,咱們用關鍵詞「extends」實現繼承。C#採用了C++的類派生語法。例如,下面的代碼顯示瞭如何派生父類Control從而建立出新類Button:
1 public class Button: Control { . . }
2.1四、最終類
因爲C#中不存在final關鍵詞,若是想要某個類再也不被派生,你可使用sealed關鍵詞,以下例所示:
sealed class FinalClass { . . }
2.1五、接口
接口這個概念在C#和Java中很是類似。接口的關鍵詞是interface,一個接口能夠擴展一個或者多個其餘接口。按照慣例,接口的名字以大寫字母「I」開頭。下面的代碼是C#接口的一個例子,它與Java中的接口徹底同樣:
1 interface IShape { void Draw(); }
擴展接口的語法與擴展類的語法同樣。例如,下例的IRectangularShape接口擴展IShape接口(即,從IShape接口派生出IRectangularShape接口)
1 interface IRectangularShape: IShape { int GetWidth(); }
若是你從兩個或者兩個以上的接口派生,父接口的名字列表用逗號分隔,以下面的代碼所示:
1 interface INewInterface: IParent1, IParent2 { }
然而,與Java不一樣,C#中的接口不能包含域(Field)。
另外還要注意,在C#中,接口內的全部方法默認都是公用方法。在Java中,方法聲明能夠帶有public修飾符(即便這並不是必要),但在C#中,顯式爲接口的方法指定public修飾符是非法的。例如,下面的C#接口將產生一個編譯錯誤。
1 interface IShape { public void Draw(); }
2.1六、is和as操做符
C#中的is操做符與Java中的instanceof操做符同樣,二者均可以用來測試某個對象的實例是否屬於特定的類型。在Java中沒有與C#中的as操做符等價的操做符。as操做符與is操做符很是類似,但它更富有「進取心」:若是類型正確的話,as操做符會嘗試把被測試的對象引用轉換成目標類型;不然,它把變量引用設置成null。
爲正確理解as操做符,首先請考慮下面這個例子中is操做符的運用。這個例子包含一個IShape接口,以及兩個實現了IShape接口的類Rectangle和Circle。
1 using System; 2 interface IShape { 3 void draw(); 4 } 5 public class Rectangle: IShape { 6 public void draw() { 7 } 8 public int GetWidth() { 9 return 6; 10 } 11 } 12 public class Circle: IShape { 13 public void draw() { 14 } 15 public int GetRadius() { 16 return 5; 17 } 18 } 19 public class LetsDraw { 20 public static void Main(String[] args) { 21 IShape shape = null; 22 if (args[0] == "rectangle") { 23 shape = new Rectangle(); 24 } 25 else if (args[0] == "circle") { 26 shape = new Circle(); 27 } 28 if (shape is Rectangle) { 29 Rectangle rectangle = (Rectangle) shape; 30 Console.WriteLine("Width : " + rectangle.GetWidth()); 31 } 32 if (shape is Circle) { 33 Circle circle = (Circle) shape; 34 Console.WriteLine("Radius : " + circle.GetRadius()); 35 } 36 } 37 }
編譯好代碼以後,用戶能夠輸入「rectangle」或者「circle」做爲Main方法的參數。若是用戶輸入的是「circle」,則shape被實例化成爲一個Circle類型的對象;反之,若是用戶輸入的是「rectangle」,則shape被實例化成爲Rectangle類型的對象。隨後,程序用is操做符測試shape的變量類型:若是shape是一個矩形,則shape被轉換成爲Rectangle對象,咱們調用它的GetWidth方法;若是shape是一個圓,則shape被轉換成爲一個Circle對象,咱們調用它的GetRadius方法。
若是使用as操做符,則上述代碼能夠改爲以下形式:
1 using System; 2 interface IShape { 3 void draw(); 4 } 5 public class Rectangle: IShape { 6 public void draw() { 7 } 8 public int GetWidth() { 9 return 6; 10 } 11 } 12 public class Circle: IShape { 13 public void draw() { 14 } 15 public int GetRadius() { 16 return 5; 17 } 18 } 19 public class LetsDraw { 20 public static void Main(String[] args) { 21 IShape shape = null; 22 if (args[0] == "rectangle") { 23 shape = new Rectangle(); 24 } 25 else if (args[0] == "circle") { 26 shape = new Circle(); 27 } 28 Rectangle rectangle = shape as Rectangle; 29 if (rectangle != null) { 30 Console.WriteLine("Width : " + rectangle.GetWidth()); 31 } 32 else { 33 Circle circle = shape as Circle; 34 if (circle != null) 35 Console.WriteLine("Radius : " + circle.GetRadius()); 36 } 37 } 38 }
在上面代碼的粗體部分中,咱們在沒有測試shape對象類型的狀況下,就用as操做符把shape轉換成Rectangle類型的對象。若是shape正好是一個Rectangle,則shape被轉換成爲Rectangle類型的對象並保存到rectangle變量,而後咱們調用它的GetWidth方法。若是這種轉換失敗,則咱們進行第二次嘗試。這一次,shape被轉換成爲Circle類型的對象並保存到circle變量。若是shape確實是一個Circle對象,則circle如今引用了一個Circle對象,咱們調用它的GetRadius方法。
2.1七、庫
C#沒有本身的類庫。可是,C#共享了.NET的類庫。固然,.NET類庫也能夠用於其餘.NET語言,好比VB.NET或者JScript.NET。值得一提的是StringBuilder類,它是對String類的補充。StringBuilder類與Java的StringBuffer類很是類似。
2.1八、垃圾收集
C++已經讓咱們認識到手工管理內存是多麼缺少效率和浪費時間。當你在C++中建立了一個對象,你就必須手工地拆除這個對象。代碼越複雜,這個任務也越困難。Java用垃圾收集器來解決這個問題,由垃圾收集器蒐集再也不使用的對象並釋放內存。C#一樣採用了這種方法。應該說,若是你也在開發一種新的OOP語言,追隨這條道路是一種很是天然的選擇。C#仍舊保留了C++的內存手工管理方法,它適合在速度極端重要的場合使用,而在Java中這是不容許的。
2.1九、異常處理
若是你據說C#使用與Java類似的異常處理機制,你不會爲此而驚訝,對吧?在C#中,全部的異常都從一個名爲Exception的類派生(聽起來很熟悉?)另外,正如在Java中同樣,你還有熟悉的try和catch語句。Exception類屬於.NET System名稱空間的一部分。
3、Java沒有的功能
C#出生在Java成熟以後,所以,C#擁有一些Java(目前)尚未的絕妙功能也就不足爲奇。
3.一、枚舉器
枚舉器即enum類型(Enumerator,或稱爲計數器),它是一個相關常量的集合。精確地說,enum類型聲明爲一組相關的符號常量定義了一個類型名字。例如,你能夠建立一個名爲Fruit(水果)的枚舉器,把它做爲一個變量值的類型使用,從而把變量可能的取值範圍
1 public class Demo { 2 public enum Fruit { 3 Apple, Banana, Cherry, Durian 4 } 5 public void Process(Fruit fruit) { 6 switch (fruit) { 7 case Fruit.Apple: 8 ... 9 break; 10 case Fruit.Banana: 11 ... 12 break; 13 case Fruit.Cherry: 14 ... 15 break; 16 case Fruit.Durian: 17 ... 18 break; 19 } 20 } 21 }
在上例的Process方法中,雖然你能夠用int做爲myVar變量的類型,可是,使用枚舉器Fruit以後,變量的取值範圍限制到了Applet、Banana、Cherry和Durian這幾個值以內。與int相比,enum的可讀性更好,自我說明能力更強。
3.二、結構
結構(Struct)與類很類似。然而,類是做爲一種引用類型在堆中建立,而結構是一種值類型,它存儲在棧中或者是嵌入式的。所以,只要謹慎運用,結構要比類快。結構能夠實現接口,能夠象類同樣擁有成員,但結構不支持繼承。
然而,簡單地用結構來取代類可能致使慘重損失。這是由於,結構是以值的方式傳遞,因爲這種傳遞方式要把值複製到新的位置,因此傳遞一個「肥胖的」結構須要較大的開銷。而對於類,傳遞的時候只需傳遞它的引用。
下面是一個結構的例子。注意它與類很是類似,只要把單詞「struct」替換成「class」,你就獲得了一個類。
1 struct Point { 2 public int x, y; 3 public Point(int x, int y) { 4 this.x = x; 5 this.y = y; 6 } 7 }
3.三、屬性
C#類除了能夠擁有域(Field)以外,它還能夠擁有屬性(Property)。屬性是一個與類或對象關聯的命名的特徵。屬性是域的一種天然擴展——二者都是有類型、有名字的類成員。然而,和域不一樣的是,屬性不表示存儲位置;相反,屬性擁有存取器(accessor),存取器定義了讀取或者寫入屬性值時必須執行的代碼。所以,屬性提供了一種把動做和讀取、寫入對象屬性值的操做關聯起來的機制,並且它們容許屬性值經過計算獲得。
在C#中,屬性經過屬性聲明語法定義。屬性聲明語法的第一部分與域聲明很類似,第二部分包括一個set過程和/或一個get過程。例如,在下面的例子中,PropertyDemo類定義了一個Prop屬性。
1 public class PropertyDemo { 2 private string prop; 3 public string Prop { 4 get { 5 return prop; 6 } 7 set { 8 prop = value; 9 } 10 } 11 }
若是屬性既容許讀取也容許寫入,如PropertyDemo類的Prop屬性,則它同時擁有get和set存取過程。當咱們讀取屬性的值時,get存取過程被調用;當咱們寫入屬性值時,set存取過程被調用。在set存取過程當中,屬性的新值在一個隱含的value參數中給出。
與讀取和寫入域的方法同樣,屬性也能夠用一樣的語法讀取和寫入。例如,下面的代碼實例化了一個PropertyDemo類,而後寫入、讀取它的Prop屬性。
1 PropertyDemo pd = new PropertyDemo(); 2 pd.Prop = "123"; // set 3 string s = pd.Prop; // get
3.四、以引用方式傳遞簡單數據類型的參數
在Java中,當你把一個簡單數據類型的值做爲參數傳遞給方法時,參數老是以值的方式傳遞——即,系統將爲被調用的方法建立一個參數值的副本。在C#中,你能夠用引用的方式傳遞一個簡單數據類型的值。此時,被調用的方法將直接使用傳遞給它的那個值——也就是說,若是在被調用方法內部修改了參數的值,則原來的變量值也隨之改變。
在C#中以引用方式傳遞值時,咱們使用ref關鍵詞。例如,若是編譯並運行下面的代碼,你將在控制檯上看到輸出結果16。注意i值被傳遞給ProcessNumber以後是如何被改變的。
1 using System; 2 public class PassByReference { 3 public static void Main(String[] args) { 4 int i = 8; 5 ProcessNumber(ref i); 6 Console.WriteLine(i); 7 } 8 public static void ProcessNumber(ref int j) { 9 j = 16; 10 } 11 }
C#中還有一個容許以引用方式傳遞參數的關鍵詞out,它與ref類似。可是,使用out時,做爲參數傳遞的變量在傳遞以前沒必要具備已知的值。在上例中,若是整數i在傳遞給ProcessNumber方法以前沒有初始化,則代碼將出錯。若是用out來取代ref,你就能夠傳遞一個未經初始化的值,以下面這個修改後的例子所示。
1 using System; 2 public class PassByReference { 3 public static void Main(String[] args) { 4 int i; 5 ProcessNumber(out i); 6 Console.WriteLine(i); 7 } 8 public static void ProcessNumber(out int j) { 9 j = 16; 10 } 11 }
通過修改以後,雖然i值在傳遞給ProcessNumber方法以前沒有初始化,但PassByReference類可以順利經過編譯。
3.五、C#保留了指針
對於那些以爲本身可以恰到好處地運用指針並樂意手工進行內存管理的開發者來講,在C#中,他們仍舊能夠用既不安全也不容易使用的「古老的」指針來提升程序的性能。C#提供了支持「不安全」(unsafe)代碼的能力,這種代碼可以直接操做指針,可以「固定」對象以便臨時地阻止垃圾收集器移動對象。不管從開發者仍是用戶的眼光來看,這種對「不安全」代碼的支持實際上是一種安全功能。「不安全」的代碼必須用unsafe關鍵詞顯式地標明,所以開發者不可能在無心之中使用「不安全」的代碼。同時,C#編譯器又和執行引擎協做,保證了「不安全」的代碼不能假裝成爲安全代碼。
1 using System; 2 class UsePointer { 3 unsafe static void PointerDemo(byte[] arr) { 4 . 5 . 6 } 7 }
C#中的unsafe代碼適合在下列情形下使用:當速度極端重要時,或者當對象須要與現有的軟件(好比COM對象或者DLL形式的C代碼)交互時。
3.六、代理
代理(delegate)能夠看做C++或者其餘語言中的函數指針。然而,與函數指針不一樣的是,C#中的代理是面向對象的、類型安全的、可靠的。並且,函數指針只能用來引用靜態函數,但代理既可以引用靜態方法,也可以引用實例方法。代理用來封裝可調用方法。你能夠在類裏面編寫方法並在該方法上建立代理,此後這個代理就能夠被傳遞到第二個方法。這樣,第二個方法就能夠調用第一個方法。
代理是從公共基類System.Delegate派生的引用類型。定義和使用代理包括三個步驟:聲明,建立實例,調用。代理用delegate聲明語法聲明。例如,一個不須要參數且沒有返回值的代理能夠用以下代碼聲明:
1 delegate void TheDelegate();
建立代理實例的語法是:使用new關鍵詞,並引用一個實例或類方法,該方法必須符合代理指定的特徵。一旦建立了代理的實例,咱們就能夠用調用方法的語法調用它。
3.七、包裝和解除包裝
在面向對象的編程語言中,咱們一般使用的是對象。但爲了提升速度,C#也提供了簡單數據類型。所以,C#程序既包含一大堆的對象,又有大量的值。在這種環境下,讓這二者協同工做始終是一個不可迴避的問題,你必需要有一種讓引用和值進行通訊的方法。
在C#以及.NET運行時環境中,這個「通訊」問題經過包裝(Boxing)和解除包裝(Unboxing)解決。包裝是一種讓值類型看起來象引用類型的處理過程。當一個值類型(簡單數據類型)被用於一個要求或者可使用對象的場合時,包裝操做自動進行。包裝一個value-type值的步驟包括:分配一個對象實例,而後把value-type值複製到對象實例。
解除包裝所執行的動做與包裝相反,它把一個引用類型轉換成值類型。解除包裝操做的步驟包括:首先檢查並確認對象實例確實是給定value-type的一個通過包裝的值,而後從對象實例複製出值。
Java對該問題的處理方式略有不一樣。Java爲每一種簡單數據類型提供了一個對應的類封裝器。例如,用Integer類封裝int類型,用Byte類封裝byte類型。
【結束語】本文爲你比較了C#和Java。這兩種語言很類似,然而,說C#是Java的克隆或許已經大大地言過其實。面向對象、中間語言這類概念並非什麼新東西。若是你準備設計一種面向對象的新語言,並且它必須在一個受管理的安全環境內運行,你難道不會搞出與C#差很少的東西嗎?