C#内存管理

一、变量类型

        C#的变量类型分为值类型,引用类型、指针类型和指令类型。所有的值类型都继承于System.ValueType,在C#中的值类型包括bool、byte、char、decimal、double、enum、float、int、long、sbyte、short、struct、uint、ulong、ushort等。在引用类型均继承自System.Object,除了Object其自身,引用类型包括class、interface、delegate、objecthe string。  一般通常了解值类型和引用类型,其中引用类型总是在堆上创建,值类型和指针类型总是在它声明的地方创建。

二、程序执行过程

public int AddFive(int pValue)
{
    int result;
    result = pValue + 5;
    return result;
}
        在程序执行过程中,在栈中为pValue、result分配内存,在方法作用域结束后将会在栈中销毁内存,如下图所示。


public class MyInt
{          
	public int MyValue;
}
执行如下:
public MyInt AddFive(int pValue)
{
	MyInt result = new MyInt();
	result.MyValue = pValue + 5;
	return result;
}

        在程序执行中,会在堆中为MyInt分配一块内存空间,同时在栈中为pValue分配空间,然后为result在栈中分配内存,此时result中存储的是MyInt在堆中的地址,方法执行完后,在栈中的result和pValue将会销毁,但MyInt将会在堆中,在GC回收时销毁。当我们达到一定内存瓶颈时我们需要堆中要有更多的空间,这时GC出场。GC将停止所有运行中的线程(完全停止),找出在堆中所有没有被引用的对象并且删除它们。GC将重新组织所有在堆中的对象以获得空间,调整所有在堆以及栈中的指针。就像你想象的那样,这将花费十分昂贵的性能,所以现在你就能看出当你在写高性能代码时,关注堆栈中有什么是如此的重要。

     注:1.GC回收一般发生在程序内存不够用时,否则不会发生除非手动调用。2.手动调用GC可实现强制“尝试”回收资源。3.GC中的所有资源是分“代”的,每次检测堆中的对象是否还有引用,如果有当前的“代”数加一,否则减一,GC回收“代”数最小的资源,这也就解释了为什么即使我手动调用GC.Collect()方法之后,对象还是没有马上被回收的问题。4.频繁调用GC.Collect()会导致频繁的线程中断,从而严重影响性能。

三、参数内存

        当我们调用方法时,如下事情将发生:当我们执行一个方法时需要在栈上创建一个空间。这包含了一个GOTO指令的地址调用(指针),所以当线程执行完我们的方法后它知道如何返回并继续执行程序。

        在栈中的参数处理分为值类型和引用类型,值类型的参数将会复制拷贝,引用类型将会拷贝引用地址。因此,如果我们有一个很大的值类型(例如很大的一个结构体)并且将它作为参数传递至方法时,每次它将被拷贝复制并且花费很大的内存和CPU时间。栈的空间是有限的,正如从水龙头往杯里灌水一样,它总会溢出的。结构体是值类型,可能会非常大,我们在使用时必须要注意。当我们在传递内存比较大的参数时,为了避免栈内存的空间浪费,可以传递指向值得引用,eg:void DoSomething(ref struct s); ref的作用是用来传递指向值得引用。此时当参数值改变时,相应的被传变量的值也会改变,参数在栈中将会保存一个指向原变量地址的地址。

  

  

    总结:

  1.  值类型当参数时,复制拷贝为一个栈上的新对象,使用后回收。

  2.  值类型当参数时,会发生拷贝现象,所以对一些“很大”的结构体类型会产生很严重的效率问题,可尝试用ref 关键字将结构体包装成引用类型进行传递,节省空间及时间。

  3.  引用类型传递的是引用地址,即多个事物指向同一个内存块,如果更改内存中的值将同时反馈到所有其引用的对象上。

  4.  Ref关键字传递的是引用类型的指针,而非引用类型地址。

四、深拷贝VS浅拷贝

        当我们对于一个引用类型赋值时,都是讲引用类型的指针进行拷贝,当一个发生改变时另一个也会改变。但我们通常需要进行深度赋值,此时一个发生改变时,另一个不会改变。

下面我们将实现这个接口:
public class Shoe : ICloneable
{
	public string Color;
	#region ICloneable Members
	public object Clone()
	{
		Shoe newShoe = new Shoe();
		newShoe.Color = Color.Clone() as string;
		return newShoe;
	}
	#endregion
}
public Dude CopyDude()
{
	Dude newPerson = new Dude();
	newPerson.Name = Name;
	newPerson.LeftShoe = LeftShoe.Clone() as Shoe;
	newPerson.RightShoe = RightShoe.Clone() as Shoe;

	return newPerson;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值