C#---引用类型,值类型和堆栈

1.值类型(System.ValueType类)和栈(Stack)

System.ValueType--bool、byte、char、decimal、double、enum、float、int、long、sbyte、short、struct、unit、ulong、ushort。

栈是编译期间就分配好的内存空间,代码中就栈的大小有明确的定义。栈是连续的内存域,由系统自动分配和维护。

  • 栈保存代码的执行步骤--函数调用返回

  A->B->C->D 函数调用压栈 返回是弹栈D->C->B->A

  •  存放变量-值类型

      值类型不一定被分配到栈上,值类型被声明在一个方法体外并且在一个引用类型中,会在堆上进行分配。(成员变量或属性)

  • 存储空间释放(垃圾回收)

      栈内存无需我们管理,也不受GC管理。栈顶元素使用完毕,立即释放。

2.引用类型(System.Object)和堆(Heap)

System.Object---class、interface、delegate、object、string

堆是程序运行期间动态分配的内存空间,可以根据程序的运行情况确定要分配的堆内存大小。堆是无序的,由用户来控制和释放,若用户不释放,当内存达到一定的特定值时,通过垃圾回收器(GC)回收。

  • 存放对象-引用类型
  • 存储空间释放

   堆则需要GC(Garbage collection:垃圾收集器)清理

在程序运行的时候,每个线程(Thread)都会维护一个自己的专属线程堆栈。

指针:

当一个方法被调用的时候,主线程开始在所属程序集的元数据中,查找被调用方法,然后通过JIT即时编译并把结果(一般是本地CPU指令)放在栈顶。CPU通过总线从栈顶取指令,驱动程序以执行下去。

3. 栈示例:

public int AddFive(int pValue)
{
int result;
result = pValue + 5;
return result;
}

方法开始调用时,方法参数在栈上分配 

方法内部开始执行时,变量result被分配在栈上

方法执行完毕,而且方法返回后

栈上的区域被清理。

4.堆示例

public class MyInt
{ 
    public int MyValue;
}
 
public MyInt AddFive(int pValue)
{
    MyInt result = new MyInt();
    result.MyValue = pValue + 5;
    return result;
}

方法被调用时,参数被分配到栈上

方法开始执行,由于MyInt是引用类型,result是指向引用类型的指针

方法执行完毕,栈上内存被清理,但堆中依然存在

当程序需要更多的堆空间时,GC需要进行垃圾清理工作,暂停所有线程,找出所有不可达到对象,即无被引用的对象,进行清理。并通知栈中的指针重新指向地址排序后的对象。当我们使用引用类型的时候,一般是对指针进行的操作而非引用类型对象本身。但是值类型则操作其本身。

 5.Dictionary<string,int> foreach无法修改值类型取值(MoveNext报错)

值类型:

Dictionary<string, int> doc = new Dictionary<string, int>();
doc.Add("sl", 1);
doc.Add("xm", 2);
doc.Add("xl", 3);
 foreach (var item in doc)
{
    Console.WriteLine(item.Value);
 }

IL代码:

.method public hidebysig static void  TestValueType() cil managed
{
  // 代码大小       106 (0x6a)
  .maxstack  3
  .locals init ([0] class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32> doc,
           [1] valuetype [mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<string,int32> V_1,
           [2] valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<string,int32> item)
  IL_0000:  nop
  IL_0001:  newobj     instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32>::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  ldstr      "sl"
  IL_000d:  ldc.i4.1
  IL_000e:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32>::Add(!0,
                                                                                                                !1)
  IL_0013:  nop
  IL_0014:  ldloc.0
  IL_0015:  ldstr      "xm"
  IL_001a:  ldc.i4.2
  IL_001b:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32>::Add(!0,
                                                                                                                !1)
  IL_0020:  nop
  IL_0021:  ldloc.0
  IL_0022:  ldstr      "xl"
  IL_0027:  ldc.i4.3
  IL_0028:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32>::Add(!0,
                                                                                                                !1)
  IL_002d:  nop
  IL_002e:  nop
  IL_002f:  ldloc.0
  IL_0030:  callvirt   instance valuetype [mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<!0,!1> class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32>::GetEnumerator()
  IL_0035:  stloc.1
  .try
  {
    IL_0036:  br.s       IL_004f
    IL_0038:  ldloca.s   V_1
    IL_003a:  call       instance valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<!0,!1> valuetype [mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<string,int32>::get_Current()
    IL_003f:  stloc.2
    IL_0040:  nop
    IL_0041:  ldloca.s   item
    IL_0043:  call       instance !1 valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<string,int32>::get_Value()
    IL_0048:  call       void [mscorlib]System.Console::WriteLine(int32)
    IL_004d:  nop
    IL_004e:  nop
    IL_004f:  ldloca.s   V_1
    IL_0051:  call       instance bool valuetype [mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<string,int32>::MoveNext()
    IL_0056:  brtrue.s   IL_0038
    IL_0058:  leave.s    IL_0069
  }  // end .try
  finally
  {
    IL_005a:  ldloca.s   V_1
    IL_005c:  constrained. valuetype [mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<string,int32>
    IL_0062:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
    IL_0067:  nop
    IL_0068:  endfinally
  }  // end handler
  IL_0069:  ret
} // end of method Program::TestValueType

引用类型:

 Dictionary<string, Student> doc = new Dictionary<string, Student>();
 Student s = new Student();
 s.name = "sl";
 s.point = 1;
 doc.Add("NO1",s);
 Student t = new Student();
 t.name = "xm";
 s.point = 2;
 doc.Add("NO2", t);
 Student st = new Student();
 st.name = "xl";
 st.point = 3;
 doc.Add("NO3", st);
foreach(var item in doc)
{
  item.Value.name = "same";
}

IL代码:

.method public hidebysig static void  TestObject() cil managed
{
  // 代码大小       184 (0xb8)
  .maxstack  3
  .locals init ([0] class [mscorlib]System.Collections.Generic.Dictionary`2<string,class TestDictionaryIL.Program/Student> doc,
           [1] class TestDictionaryIL.Program/Student s,
           [2] class TestDictionaryIL.Program/Student t,
           [3] class TestDictionaryIL.Program/Student st,
           [4] valuetype [mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<string,class TestDictionaryIL.Program/Student> V_4,
           [5] valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<string,class TestDictionaryIL.Program/Student> item)
  IL_0000:  nop
  IL_0001:  newobj     instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,class TestDictionaryIL.Program/Student>::.ctor()
  IL_0006:  stloc.0
  IL_0007:  newobj     instance void TestDictionaryIL.Program/Student::.ctor()
  IL_000c:  stloc.1
  IL_000d:  ldloc.1
  IL_000e:  ldstr      "sl"
  IL_0013:  stfld      string TestDictionaryIL.Program/Student::name
  IL_0018:  ldloc.1
  IL_0019:  ldc.i4.1
  IL_001a:  stfld      int32 TestDictionaryIL.Program/Student::point
  IL_001f:  ldloc.0
  IL_0020:  ldstr      "NO1"
  IL_0025:  ldloc.1
  IL_0026:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,class TestDictionaryIL.Program/Student>::Add(!0,
                                                                                                                                                 !1)
  IL_002b:  nop
  IL_002c:  newobj     instance void TestDictionaryIL.Program/Student::.ctor()
  IL_0031:  stloc.2
  IL_0032:  ldloc.2
  IL_0033:  ldstr      "xm"
  IL_0038:  stfld      string TestDictionaryIL.Program/Student::name
  IL_003d:  ldloc.1
  IL_003e:  ldc.i4.2
  IL_003f:  stfld      int32 TestDictionaryIL.Program/Student::point
  IL_0044:  ldloc.0
  IL_0045:  ldstr      "NO2"
  IL_004a:  ldloc.2
  IL_004b:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,class TestDictionaryIL.Program/Student>::Add(!0,
                                                                                                                                                 !1)
  IL_0050:  nop
  IL_0051:  newobj     instance void TestDictionaryIL.Program/Student::.ctor()
  IL_0056:  stloc.3
  IL_0057:  ldloc.3
  IL_0058:  ldstr      "xl"
  IL_005d:  stfld      string TestDictionaryIL.Program/Student::name
  IL_0062:  ldloc.3
  IL_0063:  ldc.i4.3
  IL_0064:  stfld      int32 TestDictionaryIL.Program/Student::point
  IL_0069:  ldloc.0
  IL_006a:  ldstr      "NO3"
  IL_006f:  ldloc.3
  IL_0070:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,class TestDictionaryIL.Program/Student>::Add(!0,
                                                                                                                                                 !1)
  IL_0075:  nop
  IL_0076:  nop
  IL_0077:  ldloc.0
  IL_0078:  callvirt   instance valuetype [mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<!0,!1> class [mscorlib]System.Collections.Generic.Dictionary`2<string,class TestDictionaryIL.Program/Student>::GetEnumerator()
  IL_007d:  stloc.s    V_4
  .try
  {
    IL_007f:  br.s       IL_009d
    IL_0081:  ldloca.s   V_4
    IL_0083:  call       instance valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<!0,!1> valuetype [mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<string,class TestDictionaryIL.Program/Student>::get_Current()
    IL_0088:  stloc.s    item
    IL_008a:  nop
    IL_008b:  ldloca.s   item
    IL_008d:  call       instance !1 valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<string,class TestDictionaryIL.Program/Student>::get_Value()
    IL_0092:  ldstr      "same"
    IL_0097:  stfld      string TestDictionaryIL.Program/Student::name
    IL_009c:  nop
    IL_009d:  ldloca.s   V_4
    IL_009f:  call       instance bool valuetype [mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<string,class TestDictionaryIL.Program/Student>::MoveNext()
    IL_00a4:  brtrue.s   IL_0081
    IL_00a6:  leave.s    IL_00b7
  }  // end .try
  finally
  {
    IL_00a8:  ldloca.s   V_4
    IL_00aa:  constrained. valuetype [mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<string,class TestDictionaryIL.Program/Student>
    IL_00b0:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
    IL_00b5:  nop
    IL_00b6:  endfinally
  }  // end handler
  IL_00b7:  ret
} // end of method Program::TestObject

 

posted @ 2019-01-08 16:49  头号程序媛  阅读(1154)  评论(0编辑  收藏  举报