在類的使用過程中,既不需要很多方法,也不需要從類中繼承,爲了提升性能,可以使用結構體來替代類。
與類不同的是,結構體用struct 修飾;結構體中的實例字段不能自定義默認值,而類可以,編譯器會隱式的給出結構體和類的默認構造函數,但是結構體的默認構造不能顯示給出,不然編譯器會報錯,當類有自定義的構造函數時,默認構造會被隱藏,要想使用默認構造,必須顯示給出;結構體的自定義構造函數必須初始化所有的實例字段和未初始化的屬性,而類不必。下面通過例子介紹結構體與類的區分,如下所示:
public class AA
{
// 類中的字段可以自定義默認值,也可以只聲明
public int a = 1;
// 只聲明的字段
public int b;
public int D{get;}
// 默認構造方法
public AA()
{
}
// 自定義構造方法,可以不用初始化沒有自定義默認值的字段和屬性
public AA(int x)
{
}
}
public struct BB
{
// 實例字段,不能在聲明的時候給出默認值
public int a;
// 靜態字段,外界可以通過結構體名訪問,可以自定義默認值,如果沒給,系統默認值0。
public static int b = 10;
// 屬性,有默認返回值
public int C{get{return 1;}}
// 屬性,沒有默認返回值
public int D{get;}
// 靜態屬性
public static int E{get;}
// 自定義的構造方法,必須初始化所有沒有自定義默認值的字段和屬性
public BB(int x)
{
a = 1;
D = x;
}
public void Test()
{
// 在結構體內部(類也可以)可以使用只聲明沒有自定義默認值的字段或屬性,結果是該類型的默認值
int f = a;
f = D;
}
}
由於結構體是值類型,所以在聲明的時候系統就已經爲他分配棧上的內存了,而 new 運算符只是調用結構體的構造函數去初始化結構體中的字段和屬性。此時可以給該結構體的實例字段賦值,但是在使用該字段的值(比如,賦值給其他變量,用作方法的參數)之前必須要進行初始化(1、調用構造函數 2、給該字段先賦值)。下面給出調用的示例:
public class Test
{
public Test()
{
// 聲明一個 BB 結構體類型的變量 bb,這是一個局部變量,使用他的實例字段之前要初始化
BB bb;
// int c = bb.a; bb.a 沒有初始化,這樣會報錯
bb.a = 1;
int c = bb.a;
}
}
public class Test1
{
// 聲明一個 BB 結構體類型的變量 bb,系統會默認調用該結構體的默認構造函數進行初始化(相當於:BB bb = new BB())
BB bb;
public Test1()
{
//這樣不會報錯,bb 已經有默認初始化
int c = bb.a;
}
}
結構體與類的不同點總結:
1、結構體是值類型,存儲在棧上,類是引用類型,存儲在託管堆上,結構體在聲明的時候就已經爲其分配棧上的內存了,而類需要用 new爲其分配堆上面的內存;
2、結構體是隱式密封的,不能用 sealed 和 abstract 修飾,結構體不能被繼承,類可以被繼承;
3、結構體中的實例字段只能聲明,不能賦值,而類沒有限制,結構體只聲明沒有用 new 進行初始化時,可以給他的實例字段賦值,而類不行;
4、結構體沒有析構函數,結構體中的方法不能用 virtual 和 abstract 修飾,但是可以用 override 修飾,用來重寫父類的方法;
4、結構體不能顯示給出默認構造函數(無參數的構造),無論有沒有自定義構造,默認構造都隱式存在,而類中有自定義構造函數時,默認構造會被隱藏,要想調用默認構造,必須顯示給出默認構造。
5、結構體的自定義構造函數必須初始化所有的實例字段和沒有初始化的非靜態屬性,類沒有限制。
結構體和類的靜態構造函數:點擊打開鏈接