C#中的結構函數
假設有一個類:佈局
class Dimensions性能
{this
public double Length;spa
public double Width;設計
}對象
定義了一個類,它只存儲某一項的長度和寬度.嘉定編寫一個佈置家居的程序,讓人們試着在計算機上從新佈置傢俱,並存儲每件傢俱的維度.使字段變爲共有字段,就會違背變成規則,但咱們實際上並不須要類的所有功能.如今只有兩個數字,把他們當作一堆來處理,要比單個處理方便一些.既不須要不少方法,也不須要從類中繼承,也不但願.NET運行庫在堆中遇到麻煩和性能問題,值存儲兩個double類型的數據便可.繼承
爲此,只須要修改代碼,使用關鍵字struct代替class,定義一個結構而不是類接口
struct Dimensions內存
{
public double Length;
public double Width;
}
爲結構定義函數與味蕾定義函數徹底相同.
struct Dimensions
{
public double Length;
public double Width;
public Dimensions(double length, double width)
{
this.Length = length;
this.Width = width;
}
public double Diagonal
{
get
{
return Math.Sqrt(Length * Length + Width * Width);
}
}
}
結構是值類型,不是引用類型.他們存儲在棧中或存儲爲內聯,其生存期的限制與簡單的數據類型同樣.
結構不支持繼承.
對於結構構造函數的工做方式有一些區別.尤爲是編譯器老是提供一個無參數的默認構造函數,他是不容許替換的.
使用結構,能夠指定字段如何在內存中的佈局.
由於結構其實是把數據項組合在一塊兒,有時大多數或者所有的字段都聲明爲public.嚴格來講,這是違背.NET代碼的規則的,根據Microsoft,字段(除了const字段以外)應該老是私有的,並由共有屬性封裝.可是對於簡單的結構,共有字段仍是能夠接受的.
結構是值類型
雖然結構是值類型,可是在語法上經常能夠把他們當作類來處理.例如,上面的Dimension類的定義中,能夠編寫下面的代碼:
Dimensions point = new Dimensions();
point.Lenth=3;
point.Width=6;
注意,由於結構是值類型,因此new運算符與類和其餘引用類型的工做方式不一樣.new運算符並不分配隊中的內存,而是隻調用相應的構造函數,根據傳送給他的參數,初始化全部的字段.對於結構,能夠編寫下面代碼:
Dimensions point;
point.Length=3;
point.Width=6;
若是Dimensions是一個類,就會產生錯誤,由於point包含一個爲初始化的引用----不知想任何地方的一個地址,因此不能給其字段設置值.可是對於結構,變量聲明其實是維護整個結構在棧中分配空間,因此就能夠爲他賦值了.
可是若是這樣:
Dimensions point;
double d=point.Length;
編譯器就會產生一個錯誤,緣由是使用了未初始化的變量.
結構遵循其餘數據類型都遵循的規則:在使用前全部的元素都必須進行初始化.在結構上調用new運算符,或者給全部的字段分別賦值,結構就徹底初始化了.若是結構定義爲類的成員字段,在初始化包含的對象時,該結構會自動初始化爲0.
結構是會影響性能的值類型.
結構不失爲繼承設計的.這意味着:他不能從一個結構中繼承.惟一的例外是對應的結構(和C#中的其餘類型同樣)最終派生於類System.Object.所以結構能夠訪問System.Object的方法.在結構中,甚至能夠重寫System.Objetc中的方法----如重寫ToString()方法.結構的繼承鏈是:每一個結構派生自System.ValueType類,System.ValueType類又派生自System.Object.ValueType並無給Object添加任何新成員,但提供了一些更適合結構的額實現方式.注意,不能爲結構提供其餘類:每一個結構都派生自ValueType.
結構的構造函數
爲結構定義構造函數的方式與爲類定義構造函數的方式相同,但不容許定義無參數的構造函數.禁止在C#的結構內使用無參數的構造函數.
前面說過,默認構造函數把數值字段都初始化爲0,把引用類型字段初始化爲null,且老是隱式的給出,及時提供了其餘帶參數的構造函數,也是如此,提供字段的初始值也不鞥呢繞過默認構造函數.
例如:
struct Dimensions
{
public double Length=1;
public double Width=2;
}
會出現錯誤,結構中不能有實例字段初始值設定項,若是是類就不會出現這個錯誤.
另外,能夠向類那樣爲結構提供Close()或Dispose()方法.
struct總結:struct 類型適於表示 Point、Rectangle 和 Color 等輕量對象。爲結構定義默認(無參數)構造函數是錯誤的。 在結構體中初始化實例字段也是錯誤的。 只能經過兩種方式初始化結構成員:一是使用參數化構造函數,二是在聲明結構後分別訪問成員。 對於任何私有成員或以其餘方式設置爲不可訪問的成員,只能在構造函數中進行初始化。
若是使用 new 運算符建立結構對象,則會建立該結構對象,並調用適當的構造函數。 與類不一樣,結構的實例化能夠不使用 new 運算符。 在此狀況下不存在構造函數調用,於是能夠提升分配效率。 可是,在初始化全部字段以前,字段將保持未賦值狀態且對象不可用。
當結構包含引用類型做爲成員時,必須顯式調用該成員的默認構造函數,不然該成員將保持未賦值狀態且該結構不可用。 (這將致使編譯器錯誤 CS0171。)
對於結構,不像類那樣存在繼承。 一個結構不能從另外一個結構或類繼承,並且不能做爲一個類的基。 可是,結構從基類 Object 繼承。 結構可實現接口,其方式同類徹底同樣。
沒法使用 struct 關鍵字聲明類。 在 C# 中,類與結構在語義上是不一樣的。 結構是值類型,而類是引用類型。