日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

base.dispose(disposing) 未将对象引用到实例_程序员深入理解asp.net c#值类型和引用类型...

發布時間:2023/12/19 C# 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 base.dispose(disposing) 未将对象引用到实例_程序员深入理解asp.net c#值类型和引用类型... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

基本概念

CLR支持兩種類型:值類型和引用類型。 面試過很多5年左右的同學,有很多連值類型和引用類型的基本概念都回答不上來,難道現在的c#開發人員基礎這么弱了嗎?還是大家都不重視基礎呢?這個隨便找一篇博客都可以基礎入門的。

引用類型

哪些類型是引用類型呢?**其實一個可以稱為”類“的類型都是引用類型**。 引用類型總是從**托管堆**上分配的,常用的語法就是New XX(). C#的new 操作符會返回對象的指針 - 也就是指向對象數據的內存地址的一個引用。引用類型的傳遞其實傳遞的是對象的指針(***string類型比較特殊***),所以在特定的場景下性能是高于值類型的。一個引用類型在創建時默認為null,也就是說當前變量不指向一個有效的對象,也就是我們常遇到的異常“未將對象引用設置到對象的實例”。

值類型

因為引用類型變量都需要進行一次堆內存的分配,這會給GC造成很大的壓力,所以CLR提供了輕量級類型“值類型”。 值類型一般在**線程棧**上分配。(注意:值類型可以嵌入一個引用對象中)一個值類型變量其實就包含了值類型實例的值,所以它沒有引用類型的指針(***大家猜想值類型需不需要類型對象指針呢?***)

相同點和不同點

相同點

1. 值類型和引用類型都是System.Object的子類

2. 值類型和引用類型都可以繼承接口。(很多人都認為值類型不能繼承接口)

interface Itest { void test(); } struct TestStruct : Itest { public void test() { throw new NotImplementedException(); } }

不同點

1. 值類型分配在堆棧上,引用類型是在托管堆上分配的。這里需要指出一點:***如果一個應用類型中的某個屬性是值類型,這個值類型的屬性是分配在托管堆上的***。

2. 所有的值類型都是隱式密封的(sealed),例如 :你不可能繼承int 來構造自己的類型。

3. 值類型的每一次賦值都會執行一次逐字段的復制,所以如果是頻繁賦值也會造成性能上的壓力,引用類型的賦值只是指針的傳遞,其實也是生成新的指針實例。

4. 引用類型額外有類型對象指針和同步塊索引,值類型是沒有的。所以我們平時使***用lock 鎖的對象不可能是值類型,因為值類型沒有同步塊索引***

性能

有的同學說值類型的性能高于引用類型,那為什么不都用值類型呢?引用類型也是如此。任何東西都有兩面性,只有合適的類型,沒有萬能的類型。

1. 值類型:所謂的.net Framework中的“輕量類型”,為什么說是“輕量”呢,這和他的內存分配有直接關系,因為值類型是分配在棧上,所以在GC的控制之外,不會對GC造成壓力。那是不是可以隨便用呢?當然不是,舉個例子:我自定義一個struct 類型作為一個方法的參數會發生什么呢?每次調用都會發生全字段的賦值,這是不可接受的,這也是典型的值類型勿用場景。

2. 引用類型:引用類型分配在堆中,所以會影響GC,如果頻繁的初始化引用類型,對GC的壓力是很大的,因為每一次分配都有可能會強制執行一次垃圾收集操作。另外提一點,引用類型的所占內存,并非所有屬性/字段的和,堆上分配的每個對象都有一些額外的成員,這些成員必須初始化。(類型對象指針和內存塊索引)。

3. 裝箱拆箱:所謂裝箱就是將值類型轉化為引用類型的過程。拆箱則相反(只是概念上相反,實際編譯器的操作不一樣)。有的同學說裝箱拆箱影響性能,那到底是裝箱影響呢還是拆箱呢還是都影響呢?

1. 裝箱發生了什么過程呢:

1. 在托管堆中分配好內存,分配的內存量是值類型的各個字段需要的內存量加上托管堆上所以對象的兩個額外成員(類型對象指針,同步塊索引)需要的內存量

2. 值類型的字段復制到新分配的堆內存中

3. 返回對象的地址,這個地址就是這個對象的引用

2. 拆箱發生了什么過程呢:

1. 獲取已經裝箱的值類型實例的指針

2. 把獲取到的值復制到棧

所以裝箱是比較耗費性能的,還有可能引發一次GC操作,而拆箱只是一個獲取指針的過程耗費資源要比裝箱小的多。注意:***一個對象拆箱之后只能還原為原先未裝箱之前的類型***,例如:你不能把int32類型裝箱后還原為int16類型。 所以面試的時候可以和面試官裝B一下了~~

測試例子

值類型引用類型分別初始化N次消耗的時間,代碼如下

static void Main(string[] args) { Console.WriteLine("test start"); int totalCount = 10000000; Stopwatch sw = new Stopwatch(); sw.Start(); for (int i = 0; i < totalCount; i++) { TestRef temp = new TestRef() { Id = i, Name = "test" }; } sw.Stop(); Console.WriteLine($"引用類型耗時:{sw.ElapsedMilliseconds}"); sw.Reset(); sw.Start(); for (int i = 0; i < totalCount; i++) { TestVal temp = new TestVal() { Id = i, Name = "test" }; } sw.Stop(); Console.WriteLine($"值類型耗時:{sw.ElapsedMilliseconds}"); Console.Read(); } class TestRef { public int Id { get; set; } public string Name { get; set; } } struct TestVal { public int Id { get; set; } public string Name { get; set; } }

運行結果:

引用類型耗時:205

值類型耗時:152

可見初始化速度值類型是優于引用類型的,也可能是引用類型引發了GC導致。

作為方法參數傳遞,代碼如下:

static void Main(string[] args) { Console.WriteLine("test start"); long totalCount = 1000000000; Stopwatch sw = new Stopwatch(); sw.Start(); TestRef tempRef = new TestRef() { Id = 1, Name = "test" , Name2="r3rewfdsafdsa

總結

以上是生活随笔為你收集整理的base.dispose(disposing) 未将对象引用到实例_程序员深入理解asp.net c#值类型和引用类型...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。