1. 程式人生 > >c#中Class和Struct使用與效能的區別

c#中Class和Struct使用與效能的區別

在Unity中很多已經定義為結構體的資料結構
  • Vector2, Vector3 和 Vector4
  • Rect
  • Color和Color32
  • Bounds
  • Touch

1.Class為引用型別,Struct為值型別

值型別與引用型別的區別這兩篇文章講得很好 雖然我們在.net中的框架類庫中,大多是引用型別,但是我們程式設計師用得最多的還是值型別。

  引用型別如:string,Object,class等總是在從託管堆上分配的,C#中new操作符返回物件的記憶體地址--也就是指向物件資料的記憶體地址。

  以下是值型別與引用型別的表:        從這張圖可以看出,class(類)
例項化出來的物件,指向了記憶體堆中分配的空間
struct(結構)例項化出來的物件,是在記憶體棧中分配    所以,值型別和引用型別的區別就是:             1、它們儲存的位置不一樣             2、如果是引用型別,當兩個物件指向同一個地方,修改某一個的時候,其它物件的值會發生改變 當說到類的例項是傳引用時,實際過程是,先獲取一個指標,它指向物件在記憶體中的地址,然後傳遞這個指標。這很重要,因為一個類的例項,實際上可能很大,包含了很多域甚至其他物件。在這種情況下,賦值和傳遞整個例項可能非常影響效能,這就為什麼要用傳地址來替代。 說到傳值時,實際過程是,對這個變數進行全克隆/拷貝,然後傳遞這個副本,原始值不變。結構體就是值型別,它是傳值的。這意味著,結構體是理想的小型資料結構。
由於引用型別在託管堆上分配,它只會在呼叫垃圾回收時才被清理。 值型別實在記憶體棧上分配,這就說明他們很容易被回收,而且不受垃圾回收的影響。 資料型別分隔為值型別和引用型別。值型別要麼是堆疊分配的,要麼是在結構中以內聯方式分配的。引用型別是堆分配的。引用型別和值型別都是從最終的基類 Object 派生出來的。當值型別需要充當物件時,就在堆上分配一個包裝(該包裝能使值型別看上去像引用物件一樣),並且將該值型別的值複製給它。該包裝被加上標記,以便系統知道它包含一個值型別。這個程序稱為裝箱,其反向程序稱為取消裝箱。裝箱和取消裝箱能夠使任何型別像物件一樣進行處理。

2.Class可以繼承父類,Struct不可以

3.Struct必須在建構函式對所有變數賦值

結構體中所有變數都必須在建構函式中初始化

4.Struct沒有預設建構函式

Struct不允許有引數為空的建構函式

5.Struct與class的效能上的優缺點

值型別的例項化之後在記憶體的大小就是其所有內容物大小,也就是內容物記憶體越大、佔用記憶體越大,存放在棧中,但是取值更快,不需要GC回收 引用型別把值存放在堆中,引用存在棧中,例項化時要在堆中取值,所以更消耗時間,但是更省記憶體,因為只用引用指標的大小,需要GC回收
值型別 引用型別
記憶體
耗時
GC

6.Struct型別變數預設不可為空

也就是說,不能寫這個語句 struct != null,如果像這樣做的話,一定要加上?,為它取值要加上Value,判斷是否為空要用HasValue Struct? struct = *****; if(struct.HasValue)      struct.Value.***** = ****; 值型別後面加問號表示可為空null(Nullable 結構) Nullable是.NET 2.0中新提供的一種用於標明一個值型別是否可以為空的技術。   對於一個型別,如果既可以給它分配一個值,也可以給它分配空引用null(表示沒有任何值),我們就說這個型別是可空的。   因此,可空型別可表示一個值,或表示不存在任何值。例如,類似 String 的引用型別就是可空型別,而類似 Int32 的值型別不是可空型別。Nullable 結構支援將值型別擴充套件為可以為null,但不支援在引用型別上使用,因為引用型別本身就是可空的。 因為值型別的容量只夠表示適合於該型別的值,因此它不可為空;值型別沒有表示空值所需的額外容量。 例:public int? age;

等同 Nullable<int>

7.其他

值型別還有一個特性就是一旦修改值,就會產生一個值型別的副本 引用型別修改值,不會產生副本,但所有有該引用的值都會被修改

8.擴充

來自《深入理解C#》
值型別很能幹,它們不需要垃圾回收,(除非被裝箱)不會因型別標識而產生開銷,也不需要解引用。
在其他方面,引用型別顯得更能幹,在傳遞引數、賦值、將值返回和執行類似的操作時,只需複製4或8位元組(要看執行的是是32位還是64位CLR),而不是賦值全部資料。
值型別傳給一個方法時,就得複製他的全部資料。
根據效能進行設計之前,需要衡量不同的選擇。
型別(不管是類還是結構體),擁有多少方法並不重要,每個例項所佔用的記憶體不會受到影響。(程式碼本身會消耗記憶體,但這隻會發生一次,而不是每個例項都發生)
-update 2017/8/6



by wolf96 2017/7/19


相關推薦

c#ClassStruct使用效能區別

在Unity中很多已經定義為結構體的資料結構 Vector2, Vector3 和 Vector4 Rect Color和Color32 Bounds Touch 1.Class為引用型別,Struct為值型別 值型別與引用型別的區別這兩篇文章講得很好 雖然我

c#ClassStruct使用性能的區別

回收 數據結構 com 垃圾回收 父類 改變 med .cn 指針 在Unity中很多已經定義為結構體的數據結構 Vector2, Vector3 和 Vector4 Rect Color和Color32 Bounds Touch 1.Class為引用類型,Str

.NET技術:.NETclassstruct區別

1、引言   提起class和struct,我們首先的感覺是語法幾乎相同,待遇卻天壤之別。歷史將接力棒由面向過程程式設計傳到面向物件程式設計,class和struct也揹負著各自的命運前行。在我認為,struct英雄遲暮,class天下獨行,最本質的區別是class是引用型別

.netclassstruct區別

  一.類與結構的示例比較: 結構示例: public struct Person { string Name; int height; int weight public bool overWeight() { //implement something

swiftclassstruct區別

// 定義class class OneClass { var name = “Deal” var age = 24 } // 定義struct struct OneStruct { var name:String

C#&&&的區別

poi log sha 與操作 位運算 orm 第一個 pre 繼續 SiKi老師讓我們自行查一下&和&&的區別,So... 1)&和&&都可以用作邏輯與的運算符,表示邏輯與(and),當運算符兩邊的表達式的結果都為tru

【轉載】C#outref之間的區別

首先:兩者都是按地址傳遞的,使用後都將改變原來引數的數值。 其次:ref可以把引數的數值傳遞進函式,但是out是要把引數清空,就是說你無法把一個數值從out傳遞進去的,out進去後,引數的數值為空,所以你必須初始化一次。這個就是兩個的區別,或者說就像有的網友說的,ref是有進有出,out是隻出不進。

SwiftClassStruct異同

Swift 中類和結構體有很多共同點。共同處在於: 定義屬性用於儲存值 定義方法用於提供功能 定義下標操作使得可以通過下標語法來訪問例項所包含的值 定義構造器用於生成初始化值 通過擴充套件以增加預設實現的功能 實現協議以提供某種標準功能 與結構體相比,類還有如下的附加功能: 繼承允許一個類繼承另一個類

關於c++結構體的區別

C++結構體內部成員變數及成員函式預設的訪問級別是public,而c++類的內部成員變數及成員函式的預設訪問級別是private。   C++結構體的繼承預設是public,而c++類的繼承預設是private。   上面兩點是最重要的兩點了個人感覺 &

c++棧的的區別(stack vs heap)

 堆和棧的區別一、預備知識—程式的記憶體分配一個由c/C++編譯的程式佔用的記憶體分為以下幾個部分1、棧區(stack)— 由編譯器自動分配釋放 ,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。2、堆區(heap) — 一般由程式設計師分配釋放, 

C++,getgetline函式的區別

cin.getline()和cin.get()都是對輸入的面向行的讀取,即一次讀取整行而不是單個數字或字元,但是二者有一定的區別。 cin.get()每次讀取一整行並把由Enter鍵生成的換行符留在輸入佇列中,比如: #include <iostr

[基礎知識]5.C++classstruct區別

C++中class與struct的區別? 如果沒有標明成員函式或者成員變數的訪問許可權級別,那麼在struct中預設的是public,而在class中預設的是private。 相關知識點: 結構體是C語言的一種自定義的資料型別,在結構體中可以含有各種不同

C++typenameclass區別

type .get true 能夠 class .... ray pla 依賴 在c++Template中很多地方都用到了typename與class這兩個關鍵字,而且好像可以替換,是不是這兩個關鍵字完全一樣呢? 相信學習C++的人對class這個關鍵字都非常明白,clas

【分析】淺談C#Control的InvokeBeginInvoke在主副線程的執行順序區別(SamWang)

info start result 初步 總結 inter blank rap 傳遞   今天無意中看到有關Invoke和BeginInvoke的一些資料,不太清楚它們之間的區別。所以花了點時間研究了下。   據msdn中介紹,它們最大的區別就是BeginInvoke屬於

C++mapset的使用區別

set set是一種關聯式容器,其特性如下: set以RBTree作為底層容器 所得元素的只有key沒有value,value就是key 不允許出現鍵值重複 所有的元素都會被自動排序 不能通過迭代器來改變set的值,因為set的值就是鍵 針對這五點來說,

徹底搞清楚 C/C++ 日期時間 time_t struct tm,time(NULL),ctime;strftime

#include <stdio.h> #include <stdlib.h> #include <time.h> int main( void ) { long i = 10000000L;

iOS---Objective-C@class#import的區別

在Objective-C的專案中, @class通常放在.h檔案中, 主要作用在於提升編譯效能, 且能防止標頭檔案的遞迴import. 編譯效能的考慮 通常, 使用#import引入一個類的標頭檔案, 編譯時會將該類的標頭檔案中的所有資訊都引入, 包含屬

C++typenameclass在宣告模板時的區別

問題 在下面的 template declarations(模板宣告)中 class 和 typename 有什麼不同? template<class T> class Widget; // uses "class" template

C#&&&,|||區別

.com blank img cnblogs png ref bsp 筆記 區別 當兩者都為邏輯運算符時。 其實沒什麽差別。 &&和||當已經確定結果時,不會對第二個操作數求值。也不知道什麽情況會用到這個差別。做個筆記好了。 http://blog.cs

C#的結構體類的區別

nbsp display 分享 pan ron none 技術分享 初始 title (一) 語法定義上的區別,定義類使用關鍵字class 定義結構使用關鍵字struct (二) 在結構體中可以聲明字段,但是聲明字段的時候是不能給初始值的. C#中的結構體與類的區