前言
這一節主要來了解一下類和結構體之間的異同點、以及針對String和StringBuilder的用法、equals和==,其實可以看出很多地方都用到了上一節的值類型和引用類型、堆棧和裝箱拆箱操作吧,慢慢的應用于實踐,讓理論與實踐結合起來。
類和結構體
類和結構體的不同點:
1.關鍵字不同 一個是class,一個是struct
2.類型不同,一個是引用類型,一個是值類型(存儲:一個堆區,一個棧區)。關于值類型和引用類型以及堆與棧詳細可見http://m.survivalescaperooms.com/aehyok/p/3504449.html
3.成員不同,結構體沒有默認的構造函數(可以添加)和沒有析構函數,不可以使用abstract,PRotected,sealed修飾
4.Struct變量使用完之后就自動解除內存分配,Class實例有垃圾回收機制來保證內存的回收處理
5.繼承性。結構不可以繼承自另一個結構或被繼承,但和類一樣可以繼承自接口
6.在結構體中可以聲明字段,但是聲明字段的時候是不能給初始值的.
7.實體類中如果我們沒有顯示的定義構造函數,那么會有一個隱式無參的構造函數(重載構造函數之后,需要顯示聲明無參構造函數),
而在結構體中隱身無參的構造函數無論如何都存在
8.在類中可以顯示的定義無參的構造函數,而在結構體中我們不能顯示的定義無參的構造函數
9.結構體是可以New的,而結構體構造函數要求必須要為所有的字段賦值.即使是無參的構造函數,也會給值類型賦初值為0,引用類型賦初值為null
同:
1.都有屬性和方法
2.和類一樣可以繼承自接口
String和StringBuilder
String對象是不可改變的。每次使用System.String類中的方法之一時,都要在內存中創建一個新的字符串對象,這就需要為該新對象分配新的空間。在需要對字符串執行重復修改的情況下,與創建新的String對象相關的系統開銷可能會非常昂貴。如果要修改字符串而不創建新的對象,則可以使用System.Text.StringBuilder類。例如,當在一個循環中將許多字符串連接在一起時,使用StringBuilder類可以提升性能。
StringBuilder MyStringBuilder = new StringBuilder("Hello World!"); 通過用一個重載的構造函數方法初始化變量,可以創建StringBuilder類的新實例,正如以下示例中所闡釋的那樣。
設置容量和長度 雖然StringBuilder對象是動態對象,允許擴充它所封裝的字符串中字符的數量,但是您可以為它可容納的最大字符數指定一個值。此值稱為該對象的容量,不應將它與當前StringBuilder對象容納的字符串長度混淆在一起。例如,可以創建StringBuilder類的帶有字符串“Hello”(長度為5)的一個新實例,同時可以指定該對象的最大容量為25。當修改StringBuilder時,在達到容量之前,它不會為其自己重新分配空間。當達到容量時,將自動分配新的空間且容量翻倍。可以使用重載的構造函數之一來指定StringBuilder類的容量。以下代碼示例指定可以將MyStringBuilder對象擴充到最大25個空白。
StringBuilder MyStringBuilder = new StringBuilder("Hello World!", 25); 另外,可以使用讀/寫 Capacity 屬性來設置對象的最大長度。以下代碼示例使用 Capacity 屬性來定義對象的最大長度。
MyStringBuilder.Capacity = 25;
EnsureCapacity方法可用來檢查當前StringBuilder的容量。如果容量大于傳遞的值,則不進行任何更改;但是,如果容量小于傳遞的值,則會更改當前的容量以使其與傳遞的值匹配。
也可以查看或設置Length屬性。如果將Length屬性設置為大于Capacity屬性的值,則自動將Capacity屬性更改為與Length屬性相同的值。如果將Length屬性設置為小于當前StringBuilder對象內的字符串長度的值,則會縮短該字符串。
這里有篇關于站長大神的博文:使用string.Format需要注意的一個性能問題http://m.survivalescaperooms.com/dudu/archive/2012/05/29/string_format_stringbuilder.html
StringBuilder,String.concat(),String+String 哪一個效率高?http://q.VEVb.com/q/36917/
equals和==
對于值類型,如果對象的值相等,則相等運算符 (==) 返回 true,否則返回 false。
對于string 以外的引用類型,如果兩個對象引用同一個對象,則 == 返回 true。對于 string 類型,== 比較字符串的值。
==操作比較的是兩個變量的值是否相等。
equals()方法比較的是兩個對象的內容是否一致,equals也就是比較引用類型是否是對同一個對象的引用。
對于值類型的比較簡單,在此我們主要來看引用類型:
public class Person { public string Name { get; set; } public Person(string name) { this.Name = name; } } class Program { static void Main(string[] args) { string a = new string(new char[] { 'h', 'e', 'l', 'l', 'o' }); string b = new string(new char[] { 'h', 'e', 'l', 'l', 'o' }); Console.WriteLine(a == b); Console.WriteLine(a.Equals(b)); object g = a; object h = b; Console.WriteLine(g == h); Console.WriteLine(g.Equals(h)); Person p1 = new Person("aehyok"); Person p2 = new Person("aehyok"); Console.WriteLine(p1 == p2); Console.WriteLine(p1.Equals(p2)); Person p3 = new Person("aehyok"); Person p4 = p3; Console.WriteLine(p3 == p4); Console.WriteLine(p3.Equals(p4)); Console.ReadLine(); } }結果輸出:

因為值類型是存儲在內存中的堆棧(以后簡稱棧),而引用類型的變量在棧中僅僅是存儲引用類型變量的地址,而其本身則存儲在堆中。
==操作比較的是兩個變量的值是否相等,對于引用型變量表示的是兩個變量在堆中存儲的地址是否相同,即棧中的內容是否相同。equals操作表示的兩個變量是否是對同一個對象的引用,即堆中的內容是否相同。
而字符串是一個特殊的引用型類型,在C#語言中,重載了string 對象的很多方法方法(包括equals()方法),使string對象用起來就像是值類型一樣。因此在上面的例子中,字符串a和字符串b的兩個比較是相等的。
而g.equals(h)用的是sting的equals()方法故相等(多態)。如果將字符串a和b作這樣的修改: string a="aa"; string b="aa";則,g和h的兩個比較都是相等的。這是因為系統并沒有給字符串b分配內存,只是將"aa"指向了b。所以a和b指向的是同一個字符串(字符串在這種賦值的情況下做了內存的優化)。
對于p1和p2,也是內存中兩個不同的對象,所以在內存中的地址肯定不相同,故p1==p2會返回false,又因為p1和p2又是對不同對象的引用,所以p1.equals(p2)將返回false。對于p3和p4,p4=p3,p3將對對象的引用賦給了p4,p3和p4是對同一個對象的引用,所以兩個比較都返回true。
新聞熱點
疑難解答