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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

.NET 类型(Types)的那些事

發布時間:2023/11/30 asp.net 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 .NET 类型(Types)的那些事 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

引言

您是.Net工程師?那 .NetFramework中的類型您知道有三大類嗎?(除了引用類型和值類型,還有?)

引用類型一定在“堆”上,值類型一定在“棧”上?

那引用類型在內存中的布局細節您又知道多少了?

?

.Net Framework 中的Types分類

?

C# type categorization. 帶陰影的都是 C# 的內建類型關鍵字.

除了object and string(分別為System.Object System.String別名), 其他帶陰影的都是簡單的值類型.

下面是摘自《C#語言規范5.0》 –> 4.類型(page:77)

C# 語言的類型劃分為兩大類:值類型 (Value type) 和引用類型 (reference type)。

第三種類型是指針,只能用在不安全代碼中。

引用類型和值類型在內存中如何分配的呢?

這一塊我們將通過一小段代碼來講解,在講解前讓我們回顧下

引用類型 和值類型的賦值過程中在內存處理上的區別:

  • 把一個值類型a(定義如下int a=80;)賦給另外一個值類型b(int b;),即(b=a;)時,會把a的值拷貝一份給a,如下圖;

  • 把一個引用類型a(定義如下Employee a=new employee();)賦給另外一個引用類型b(Employee b;),即(b=a;)時,會把a的地址(引用)拷貝一份給a,即他們指向同一個地址;

開始代碼講解,首先看代碼如下:

Form myForm = new Form(); Size s = new Size (100, 100); // struct = value type Font f = new Font (“Arial”,10); // class = reference type myForm.Size = s; myForm.Font = f;

注意代碼中 myForm.Size中的Size和myForm.Font的Font是Form類型的屬性(Property)不是類型(class type,代表某個類型)。

在.NetFramework中這樣的使用方式極其普遍,初學者不要混淆了這兩者。

講解代碼前給大家再提下知識點:

  • Size是Struct類型,當然就是值類型(ValueType)
  • Font是Class類型,當然就是引用類型(ReferenceType)

?

上面這段代碼的內存中的分配,示意圖:

很清楚地看到

  • Size類型的s分配到了Stack上,而Front類型的f 和Form類型的myForm則分配在堆上。
  • 并且myForm的Font屬性引用到了Font類型f。
  • myForm的Size屬性有它自己的值(Width和Height),它是Size類型s的一個拷貝。

這里我們更清晰的看到了值類型和引用類型在值賦值過程中的區別

我們可以通過修改Font類型f的值,來修改myForm中的字體樣式,但不能通過修改s來修改myFrom的Size。

引用類型的Object內存布局基礎結構

上面這個圖展示的結構是通過分析源碼得出的:

  • 首先ObjectHeader(在其所在的AppDomain中的那個Thread通過調用Monitor.Enter鎖了這個對象)
  • 接下來是Method Table 指針(該指針指向AppDomain中聲明(定義)托管類型),如果程序集被加載到AppDomain neutral 中,那么所有的AppDomain中該類型實例的Method Table指針都一樣。CLR 類型系統的該基礎構建塊在托管代碼中都是可視的。(TypeHandle.Value 是一個IntPtr)
  • 最后就是這部分就是該類型實例的值。
  • CLR object的這個實例對象的地址在垃圾回收時也有可能會發生變動。(具體參看GC中壓縮過程)

    ?

    \sscli20\clr\src\vm\object.h

    // // The generational GC requires that every object be at least 12 bytes // in size. #define MIN_OBJECT_SIZE (2*sizeof(BYTE*) + sizeof(ObjHeader))

    A .NET object has basically this layout:

    class Object {protected:MethodTable* m_pMethTab;}; class ObjHeader {private:// !!! Notice: m_SyncBlockValue *MUST* be the last field in ObjHeader.DWORD m_SyncBlockValue; // the Index and the Bits };
    Platform最小實例大小(bytes)
    x8612 bytes = 2*4+4
    x64 24 bytes = 2*8+8

    ?

    引用類型的Object內存布局代表性結構

    ?

    普通對象

    ?

    數組對象 - Array

    字符串對象

    ?

    Boxing,小心您的值類型不經意間被裝箱

    ?

    int a=1; object b=a;

    這段代碼大家都知道會發生裝箱,裝箱后原來的值類型會有哪些變化?看下裝箱和拆箱的步驟:

    裝箱:
    對值類型在堆中分配一個對象實例,并將該值復制到新的對象中。按三步進行。
    第一步:新分配托管堆內存(大小為值類型實例大小加上一個方法表指針和一個SyncBlockIndex)。
    第二步:將值類型的實例字段拷貝到新分配的內存中。
    第三步:返回托管堆中新分配對象的地址。這個地址就是一個指向對象的引用了。
    有人這樣理解:如果將Int32裝箱,返回的地址,指向的就是一個Int32。我認為也不是不能這樣理解,但這確實又有問題,一來它不全面,二來指向Int32并沒說出它的實質(在托管堆中)。
    拆箱:
    檢查對象實例,確保它是給定值類型的一個裝箱值。將該值從實例復制到值類型變量中。
    有書上講,拆箱只是獲取引用對象中指向值類型部分的指針,而內容拷貝則是賦值語句之觸發。我覺得這并不要緊。最關鍵的是檢查對象實例的本質,拆箱和裝箱的類型必需匹配,這一點上,在IL層上,看不出原理何在,我的猜測,或許是調用了類似GetType之類的方法來取出類型進行匹配(因為需要嚴格匹配)。

    那么給你個自定義結構體,你還清楚什么情況會被裝箱嗎?

    參考《防止裝箱落實到底,只做一半也是失敗》

    附加

    為方便大家查看源碼,這里提供一個源碼索引表

    SSCLI文件索引

    ItemSSCLI Path
    AppDomain\sscli\clr\src\vm\appdomain.hpp
    AppDomainStringLiteralMap\sscli\clr\src\vm\stringliteralmap.h
    BaseDomain\sscli\clr\src\vm\appdomain.hpp
    ClassLoader\sscli\clr\src\vm\clsload.hpp
    EEClass\sscli\clr\src\vm\class.h
    FieldDescs\sscli\clr\src\vm\field.h
    GCHeap\sscli\clr\src\vm\gc.h
    GlobalStringLiteralMap\sscli\clr\src\vm\stringliteralmap.h
    HandleTable\sscli\clr\src\vm\handletable.h
    InterfaceVTableMapMgr\sscli\clr\src\vm\appdomain.hpp
    Large Object Heap\sscli\clr\src\vm\gc.h
    LayoutKind\sscli\clr\src\bcl\system\runtime\interopservices\layoutkind.cs
    LoaderHeaps\sscli\clr\src\inc\utilcode.h
    MethodDescs\sscli\clr\src\vm\method.hpp
    MethodTables\sscli\clr\src\vm\class.h
    OBJECTREF\sscli\clr\src\vm\typehandle.h
    SecurityContext\sscli\clr\src\vm\security.h
    SecurityDescriptor\sscli\clr\src\vm\security.h
    SharedDomain\sscli\clr\src\vm\appdomain.hpp
    StructLayoutAttribute\sscli\clr\src\bcl\system\runtime\interopservices\attributes.cs
    SyncTableEntry\sscli\clr\src\vm\syncblk.h
    System namespace\sscli\clr\src\bcl\system
    SystemDomain\sscli\clr\src\vm\appdomain.hpp
    TypeHandle\sscli\clr\src\vm\typehandle.h

    更多源碼參考http://www.projky.com/dotnet

    參考

    ?

    The Truth About .NET Objects And Sharing Them Between AppDomains

    Six important .NET concepts: Stack, heap, value types, reference types, boxing, and unboxing

    Shared Source Common Language Infrastructure

    [翻譯經典文章]深入.NET Framework內部, 看看CLR如何創建運行時對象的

    .NET對象的內存布局

    托管堆與垃圾收集

    C# 裝箱和拆箱[整理]

    mdsn?類型詳解(Jit and Run)

    轉載于:https://www.cnblogs.com/HQFZ/p/4638794.html

    總結

    以上是生活随笔為你收集整理的.NET 类型(Types)的那些事的全部內容,希望文章能夠幫你解決所遇到的問題。

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