C#是達成微軟公共語言運行庫(CLR)的少數語言中的一種。達成CLR的語言可以受益于其帶來的特性,如跨語言集成、異常處理、安全性增強、部件組合的簡易模型以及調試和分析服務。作為現代的CLR語言,C#是應用最為廣泛的,其應用場景針對Windows桌面、移動手機以及服務器環境等復雜、專業的開發項目。
C#是種面向對象的強類型語言。C#在編譯和運行時都有的強類型檢查,使在大多數典型的編程錯誤能夠被盡早地發現,而且位置定位相當精準。相比于那些不拘泥類型,在違規操作很久后才報出可追蹤到莫名其妙錯誤的語言,這可以為程序員節省很多時間。然而,許多程序員有意或無意地拋棄了這個檢測的有點,這導致本文中討論的一些問題。
本文介紹了10種最常見的編程錯誤,或是C#程序員要避免的陷阱。
盡管本文中討論的錯誤是C#環境下的,但對其他達成CLR或使用框架類庫(FCL)的語言也相關(FCL)。

C++以及許多其他語言的程序員習慣于控制他們分配給變量的值是否為簡易的值或現有對象的引用。在C#中呢,這將由寫該對象的程序員決定,而不是由實例化該對象并對它進行變量賦值的程序員決定。這是新手C#程序員們的共同“問題”。
如果你不知道你正在使用的對象是否是值類型或引用類型,你可能會遇到一些驚喜。例如:
| 1234567891011 | Point point1 = new Point(20, 30);Point point2 = point1;point2.X = 50;Console.WriteLine(point1.X); // 20 (does this surPRise you?)Console.WriteLine(point2.X); // 50Pen pen1 = new Pen(Color.Black);Pen pen2 = pen1;pen2.Color = Color.Blue;Console.WriteLine(pen1.Color); // Blue (or does this surprise you?)Console.WriteLine(pen2.Color); // Blue |
如你所見,盡管Point和Pen對象的創建方式相同,但是當一個新的X的坐標值被分配到point2時, point1的值保持不變 。而當一個新的color值被分配到pen2,pen1也隨之改變。因此,我們可以推斷point1和point2每個都包含自己的Point對象的副本,而pen1和pen2引用了同一個Pen對象 。如果沒有這個測試,我們怎么能夠知道這個原理?
一種辦法是去看一下對象是如何定義的(在Visual Studio中,你可以把光標放在對象的名字上,并按下F12鍵)
| 12 | publicstructPoint{…}//definesa“value”typepublicclassPen{…}//definesa“reference”type |
如上所示,在C#中,struct關鍵字是用來定義一個值類型,而class關鍵字是用來定義引用類型的。對于那些有C++編程背景人來說,如果被C++和C#之間某些類似的關鍵字搞混,可能會對以上這種行為感到很吃驚。
如果你想要依賴的行為會因值類型和引用類型而異,舉例來說,如果你想把一個對象作為參數傳給一個方法,并在這個方法中修改這個對象的狀態。你一定要確保你在處理正確的類型對象。
在C#中,值得類型不能為空。根據定義,值的類型值,甚至初始化變量的值類型必須有一個值。這就是所謂的該類型的默認值。這通常會導致以下,意想不到的結果時,檢查一個變量是否未初始化:
| 123456 | classProgram{staticPointpoint1;staticPenpen1;staticvoidMain(string[]args){Console.WriteLine(pen1==null);//TrueConsole.WriteLine(point1==null);//False(huh?)}} |
為什么不是【point 1】空?答案是,點是一個值類型,和默認值點(0,0)一樣,沒有空值。未能認識到這是一個非常簡單和常見的錯誤,在C#中
很多(但是不是全部)值類型有一個【IsEmpty】屬性,你可以看看它等于默認值:
| 1 | Console.WriteLine(point1.IsEmpty);//True |
當你檢查一個變量是否已經初始化,確保你知道值未初始化是變量的類型,將會在默認情況下,不為空值。
在C#中有很多方法來比較字符串。
雖然有不少程序員使用==操作符來比較字符串,但是這種方法實際上是最不推薦使用的。主要原因是由于這種方法沒有在代碼中顯示的指定使用哪種類型去比較字符串。
相反,在C#中判斷字符串是否相等最好使用Equals方法:
| 1 | publicboolEquals(stringvalue);publicboolEquals(stringvalue,StringComparisoncomparisonType); |
第一個Equals方法(沒有comparisonType這參數)和使用==操作符的結果是一樣的,但好處是,它顯式的指明了比較類型。它會按順序逐字節的去比較字符串。在很多情況下,這正是你所期望的比較類型,尤其是當比較一些通過編程設置的字符串,像文件名,環境變量,屬性等。在這些情況下,只要按順序逐字節的比較就可以了。使用不帶comparisonType參數的Equals方法進行比較的唯一一點不好的地方在于那些讀你程序代碼的人可能不知道你的比較類型是什么。
使用帶comparisonType的Equals方法去比較字符串,不僅會使你的代碼更清晰,還會使你去考慮清楚要用哪種類型去比較字符串。這種方法非常值得你去使用,因為盡管在英語中,按順序進行的比較和按語言區域進行的比較之間并沒有太多的區別,但是在其他的一些語種可能會有很大的不同。如果你忽略了這種可能性,無疑是為你自己在未來的道路上挖了很多“坑”。舉例來說:
| 123456789101112 | strings="strasse";//outputsFalse:Console.WriteLine(s=="straße");Console.WriteLine(s.Equals("straße"));Console.WriteLine(s.Equals("straße",StringComparison.Ordinal));Console.WriteLine(s.Equals("Straße",StringComparison.CurrentCulture));Console.WriteLine(s.Equals("straße",StringComparison.OrdinalIgnoreCase));//outputsTrue:Console.WriteLine(s.Equals("straße",StringComparison.CurrentCulture));學習交流
熱門圖片
猜你喜歡的新聞
猜你喜歡的關注
新聞熱點 2021-11-16 21:31:39
2021-11-02 13:59:17
2021-11-02 13:52:17
2021-11-01 13:36:51
2021-11-01 13:34:27
2021-11-01 12:56:36
疑難解答 |