.NET 类型(Types)的那些从

引言

汝是.Net工程师?那 .NetFramework中的色您了解出三死类为?(除了引用类型和值类型,还有?)

援类型一定在“堆”上,值类型一定当“栈”上?

那引用类型在内存中的布局细节而又懂有些了?

 

.Net Framework 中的Types分类

 

图片 1

C# type categorization. 带阴影的都是 C# 的内建类型主要字.

除了objectand 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,如下图;

图片 2

  • 将一个引用类型a(定义如下Employee a=new
    employee();)赋给另外一个援类型b(Employee
    b;),即(b=a;)时,会把a的地点(引用)拷贝一客让a,即他们对同一个地址;

图片 3

开班代码讲解,首先看代码如下:

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)

 

地方这段代码的内存中之分配,示意图:

图片 4

十分理解地看来

  • Size类型的s分配到了Stack上,而Front类型的f 和Form类型的myForm则分配在堆上。
  • 并且myForm的Font属性引用到了Font类型f。
  • myForm的Size属性有其自己之值(Width和Height),它是Size类型s的一个拷贝。

这边我们重清楚的见到了价值类型和援类型在值赋值过程被的别

咱得以经过修改Font类型f的价值,来修改myForm中之字样式,但未克通过修改s来窜myFrom的Size。

援类型的Object内存布局基础结构

图片 5

方是图展示的布局是透过分析源码得出的:

  1. 率先ObjectHeader(在其所于的AppDomain中之不可开交Thread通过调用Monitor.Enter锁了此目标)
  2. 通下是Method Table
    指针(该指针指向AppDomain中宣称(定义)托管型),如果程序集为加载到AppDomain
    neutral 中,那么具有的AppDomain中该型实例的Method
    Table指针都一致。CLR
    类型系统的欠基础构建块当托管代码中都是可视的。(TypeHandle.Value
    是一个IntPtr.aspx))
  3. 最后就是是就有尽管是该档实例的价。

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)
x86 12 bytes = 2*4+4
x64 24 bytes = 2*8+8

 

引用类型的Object内存布局代表性结构

 

常见对象

 

图片 6

数组对象 – Array

图片 7

字符串对象

图片 8

 

Boxing,小心您的值类型不经意间让装箱

 

int a=1;
object b=a;

这段代码大家还知情会发生装箱,装箱后原本的值类型会发出什么样变化?看下装箱和拆箱的手续:

装箱:
本着值类型在积着分配一个对象实例,并拿该值复制到新的目标中。按三步进行。
首先步:新分配托管堆内存(大小为值类型实例大小加上一个主意表指针和一个SyncBlockIndex)。
其次步:将值类型的实例字段拷贝到新分配的内存中。
其三步:返回托管堆中新分配对象的地点。这个地点便是一个对对象的援了。
有人这么懂:如果拿Int32装箱,返回的地方,指向的虽是一个Int32。我认为吧不是不可知如此敞亮,但随即着实又生题目,一来它不周到,二来指于Int32并不曾说发它的真相(在托管堆中)。
拆箱:
反省对象实例,确保它们是深受定值类型的一个装箱值。将该值从实例复制到值类型变量中。
有开及谈,拆箱只是获取引用对象吃因于值类型部分的指针,而内容拷贝则是赋值语句的点。我道这并无急。最关键的凡检查对象实例的庐山真面目,拆箱和装箱的品种必需匹配,这一点达成,在IL层上,看无产生原理何在,我的怀疑,或许是调用了仿佛GetType之类的主意来取出类型进行匹配(因为需要从严匹配)。

那么被您个自定义结构体,你还了解什么状态会吃装箱吗?

参考《谨防装箱落实到底,只开一半吧是没戏》

附加

啊便利大家查看源码,这里提供一个源码索引表

SSCLI文件目录

Item SSCLI 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)