淺析C# 結(jié)構(gòu)體struct
結(jié)構(gòu)體
有時候我們僅需要一個小的數(shù)據(jù)結(jié)構(gòu),類提供的功能多于我們需要的功能;考慮到性能原因,最好使用結(jié)構(gòu)體。
結(jié)構(gòu)體是值類型,存儲在棧中或存儲為內(nèi)聯(lián)(如果結(jié)構(gòu)體是存儲在堆中的另一個對象的一部分)。
例如類class:
public class Dimensions { public Dimensions(double length, double width) { Length = length; Width = width; } public double Length { get; set; } public double Width { get; set; } }
可以使用結(jié)構(gòu)體struct替換:
public struct Dimensions { public Dimensions(double length, double width) { Length = length; Width = width; } public double Length { get; set; } public double Width { get; set; } }
也可以為結(jié)構(gòu)體struct創(chuàng)建函數(shù),和給類創(chuàng)建函數(shù)完全相同:
public struct Dimensions { public Dimensions(double length, double width) { Length = length; Width = width; } public double Length { get; set; } public double Width { get; set; } public double Diagonal => Math.Sqrt(Length * Length + Width * Width); }
結(jié)構(gòu)體初始化
結(jié)構(gòu)體是值類型,但在使用時的語法和類基本一模一樣。例如對于上面定義的類或結(jié)構(gòu)體,均可使用代碼:
Dimensions point = new Dimensions(3, 6);
注意:
因為結(jié)構(gòu)體是值類型,所以new運算符與類和其他引用類型的工作方式不同。
用于結(jié)構(gòu)體struct的new運算符并不分配堆中的內(nèi)存,而是只調(diào)用相應(yīng)的構(gòu)造函數(shù),根據(jù)傳送給它的參數(shù),初始化所有字段。
對于結(jié)構(gòu),變量聲明實際上是韋整個結(jié)構(gòu)在棧中分配空間。例如用如下語法(如果是類的話,就會編譯錯誤):
Dimensions point; //直接省略new point.Length = 3; point.Width = 6;
結(jié)構(gòu)體遵循其他數(shù)據(jù)類型都遵守的規(guī)則:在使用前所有元素都必須進行初始化。
結(jié)構(gòu)體的初始化方法:
- 使用new運算符
- 給所有的字段直接賦值
結(jié)構(gòu)體性能影響
- 為結(jié)構(gòu)體分配內(nèi)存時,速度非??欤驗樗鼈儗?nèi)聯(lián)或者保存在棧中。結(jié)構(gòu)體超出作用域被刪除時,速度也很快,不需要等待垃圾收集。
- 如果把結(jié)構(gòu)體作為參數(shù)來傳遞,或者把一個結(jié)構(gòu)體賦值給另一個結(jié)構(gòu)體,結(jié)構(gòu)體的所有內(nèi)容就會被復(fù)制;這樣就會有性能損失。這也是為什么結(jié)構(gòu)體主要用于小的數(shù)據(jù)結(jié)構(gòu)。
- 把結(jié)構(gòu)體作為參數(shù)傳遞給方法時,應(yīng)該把它作為ref參數(shù)傳遞 - 此時只傳遞了結(jié)構(gòu)體在內(nèi)存中地址。
只讀結(jié)構(gòu)體
C#7.2開始,readonly修飾符可以應(yīng)用于結(jié)構(gòu)體struct,因此編譯器保證結(jié)構(gòu)體的不變性。
public readonly struct Dimensions { public Dimensions(double length, double width) { Length = length; Width = width; } public double Length { get; } public double Width { get; } public double Diagonal => Math.Sqrt(Length * Length + Width * Width); }
對于readonly修飾符,如果在創(chuàng)建對象后類型更改了字段或?qū)傩?,編譯器就會報錯。
使用readonly編譯器可以生成優(yōu)化的代碼,使其在傳遞結(jié)構(gòu)體時不會復(fù)制結(jié)構(gòu)體的內(nèi)容;
相反,編譯器使用引用,因為它永遠不會改變。
注意:上面readonly結(jié)構(gòu)體的屬性是只讀的,只有g(shù)et;如果有set的話,編譯會報錯:
error CS8341: Auto-implemented instance properties in readonly structs must be readonly.
結(jié)構(gòu)體和類 - 值類型和引用類型
using System; namespace value_reference { public struct A { public int x { get; set; } } public class B { public int x { get; set; } } class Program { public static void UpdateStructValue(A a) { a.x = 10; } public static void UpdateObjectValue(B b) { b.x = 10; } static void Main(string[] args) { var a = new A { x = 1 }; var b = new B { x = 1 }; UpdateStructValue(a); UpdateObjectValue(b); Console.WriteLine($"a.x -> {a.x}"); Console.WriteLine($"b.x -> {b.x}"); } } }
輸出結(jié)果:
$ dotnet run
a.x -> 1
b.x -> 10
以上就是淺析C# 結(jié)構(gòu)體struct 的詳細內(nèi)容,更多關(guān)于C# 結(jié)構(gòu)體struct 的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C# 微信支付 wx.chooseWXPay 簽名錯誤的解決方法
本篇文章主要介紹了C# 微信支付 wx.chooseWXPay 簽名錯誤的解決方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-12-12C#.net實現(xiàn)在Winform中從internet下載文件的方法
這篇文章主要介紹了C#.net實現(xiàn)在Winform中從internet下載文件的方法,實例分析了基于Winform實現(xiàn)文件下載的相關(guān)技巧,需要的朋友可以參考下2015-07-07在winform中實現(xiàn)雙向數(shù)據(jù)綁定的方法
雙向數(shù)據(jù)綁定是一種允許我們創(chuàng)建持久連接的技術(shù),使模型數(shù)據(jù)和用戶界面(UI)之間的交互能夠自動同步,今天我想通過winform中DataGridView控件為例,介紹在winform中如何實現(xiàn)雙向數(shù)據(jù)綁定,需要的朋友可以參考下2024-03-03