区分值类型和引用类型
在C#中两种类型的数据:值类型数据,引用类型数据。
在编码时区分,可避免一些细小的编码错误。
值类型:例如:int、float、bool之类的基础类型,以及用struct定义的类型,如:DateTime。
引用类型:如string,数组,以及用class定义的类型等都是引用类型
| 值类型 | 值类型 |
内存分配地点 | 分配在栈中 | 分配在堆中 |
效率 | 效率高,不需要地址转换 | 效率低,需要进行地址转换 |
内存回收 | 使用完后,立即回收 | 使用完后,不是立即回收,等待GC回收 |
赋值操作 | 进行复制,创建一个同值新对象 | 只是对原有对象的引用 |
函数参数与返回值 | 是对象的复制 | 是原有对象的引用,并不产生新的对象 |
类型扩展 | 不易扩展 | 容易扩展,方便与类型扩展 |
总结经验1:如果需要在函数中对值类型参数进行修改,需要用ref或者out进行标识才能真正实现 2:引用类型来说,当其作为函数参数的时候,不希望在函数中被修改,如: public void AddValue( MyType typValue ) { } 解决方法:需要给此类型提供clone函数
public class MyType:ICloneable
{
private int nCount = 0;
public int Count
{
set{ nCount = value;}
get{ return nCount;}
}
public MyType()
{
}
public MyType( int Value)
{
nCount = Value;
}
#region ICloneable Members
public object Clone()
{
// TODO: Add MyType.Clone implementation
return new MyType( nCount );
}
#endregion
}
那么在调用的时候,用当前的对象的clone作为参数即可。
在C#中,尤其自己定义类型的时候,常常由于是用struct来定义还是用class来定义,即是定义一个值类型还是一个引用类型呢。在这本书上给了几个判定条件,如果如下几点都满足的话,建议用struct来定义为值类型,否则用class定义为引用类型。
<!--[if !supportLists]-->1<!--[endif]-->这个类型是否主要为了数据存储;
<!--[if !supportLists]-->2<!--[endif]-->是否只通过属性来访问对象的数据成员;
<!--[if !supportLists]-->3 <!--[endif]-->这个类型是否不会有子类型;
<!--[if !supportLists]-->4<!--[endif]-->在程序处理的时候不会把这个类型对象通过多态来处理。
总而言之,在C#中,就是把底层面的数据用值类型来处理,而包含复杂操作,需要进行扩展的数据用引用类型来处理。