[你必须知道的.NET]第九回:品味类型---值类型与引用类型(中)
转自:http://www.cnblogs.com/anytao/archive/2007/05/28/must_net_09.html 接上回[第八回:品味类型---值类型与引用类型(上)-内存有理]的探讨,继续我们关注值类型和引用类型的话题。 本文将介绍以下内容:
1.引言 上回[第八回:品味类型---值类型与引用类型(上)-内存有理]的发布,受到大家的不少关注,我们从内存的角度了解了值类型和引用类型的所以然,留下的任务当然是如何应用类型的不同特点在系统设计、性能优化等方面发挥其作用。因此,本回是对上回有力的补充,同时应朋友的希望,我们尽力从内存调试的角度来着眼一些设计的分析,这样就有助于对这一主题进行透彻和全面的理解,当然这也是下一回的重点。 从内存角度来讨论值类型和引用类型是有理有据的,而从规则的角度来了解值类型和引用类型是无边无际的。本文旨在从上文呼应的角度,来把这个主题彻底的融会贯通,无边无迹的应用,还是来自反复无常的实践,因此对应用我只能说以一个角度来阐释观点,但是肯定不可能力求全局。因此,我们从以下几个角度来完成对值类型与引用类型应用领域的讨论。 2. 通用规则与比较 通用有规则:
简单的说是由于string的immutable特性,因此每次对string的改变都会在托管堆中产生一个新的string变量,上述string作为参数传递时,实际上执行了s=s操作,在托管堆中会产生一个新的空间,并执行数据拷贝,所以才有了类似于按值传递的结果。但是根据我们的内存分析可知,string在本质上还是一个引用类型,在参数传递时发生的还是按址传递,不过由于其特殊的恒定特性,在函数内部新建了一个string对象并完成初始化,但是函数外部取不到这个变化的结果,因此对外表现的特性就类似于按值传递。至于string类型的特殊性解释,我推荐Artech的大作《深入理解string和如何高效地使用string》。 另外,string类型重载了==操作符,在类型比较是比较的是实际的字符串,而不是引用地址,因此有以下的执行结果:
string
aString
=
"
123
"
;
string bString = " 123 " ; Console.WriteLine((aString == bString)); // 显示为true,等价于aString.Equals(bString); string cString = bString; cString = " 456 " ; Console.WriteLine((bString == cString)); // 显示为false,等价于bString.Equals(cString);
public
struct
MyStructTester
{} public class isValueType_Test { public static void Main() { MyStructTesteraStruct = new MyStructTester(); Typetype = aStruct.GetType(); if (type.IsValueType) { Console.WriteLine( " {0}belongstovaluetype. " ,aStruct.ToString()); } } }
MyStructaTest;
Console.WriteLine(aTest.X);
char
a
=
'
c
'
;
char b = ' c ' ; Console.WriteLine((a.Equals(b))); // 会返回true;
比较出真知:
3. 对症下药-应用场合与注意事项 现在,在内存机制了解和通用规则熟悉的基础上,我们就可以很好的总结出值类型和引用类型在系统设计时,如何作出选择?当然我们的重点是告诉你,如何去选择使用值类型,因为引用类型才是.NET的主体,不必花太多的关照就可以赢得市场。 3.1 值类型的应用场合
3.2 引用类型的应用场合
4. 再论类型判等 类型的比较通常有Equals()、ReferenceEquals()和==/!=三种常见的方法,其中核心的方法是Equals。我们知道Equals是System.Object提供的虚方法,用于比较两个对象是否指向相同的引用地址,.NET Framework的很多类型都实现了对Equals方法的重写,例如值类型的“始祖”System.ValueType就重载了Equal方法,以实现对实例数据的判等。因此,类型的判等也要从重写或者重载Equals等不同的情况具体分析,对值类型和引用类型判等,这三个方法各有区别,应多加注意。 4.1 值类型判等
4.2 引用类型判等
public
virtual
bool
Equals(
object
obj);
public static bool Equals( object objA, object objB); 一种是虚方法,默认为引用地址比较;而静态方法,如果objA是与objB相同的实例,或者如果两者均为空引用,或者如果objA.Equals(objB)返回true,则为true;否则为false。.NET的大部分类都重写了Equals方法,因此判等的返回值要根据具体的重写情况决定。
有必要在自定义的类型中,实现对Equals和==的重写或者重载,以提高性能和针对性分析。 5. 再论类型转换 类型转换是引起系统异常一个重要的因素之一,因此在有必要在这个主题里做以简单的总结,我们不力求照顾全面,但是追去提纲挈领。常见的类型转换包括:
(type)(变量、表达式)
例如:int a = (int)(b + 2.02);
static
访问修饰操作符转换修饰操作符
operator
类型(参数列表);
例如:
public
Student
{ // static public expliciteopertatorStudent( string name, int age) { return new Student(name,age); } // } 其中,所有的转换都必须是static的。 6. 结论 现在,我们从几个角度延伸了上回对值类型和引用类型的分析,正如本文开头所言,对类型的把握还有很多可以挖掘的要点,但是以偏求全的办法我认为还是可取的,尤其是在技术探求的过程中,力求面面俱到的做法并不是好事。以上的几个角度,我认为是对值类型和引用类型把握的必经之路,否则在实际的系统开发中常常会在细小的地方栽跟头,摸不着头脑。 品味类型,我们以应用为要点撬开值类型和引用类型的规矩与方圆。 品味类型,我们将以示例为导航,开动一个层面的深入分析,下回《第十回:品味类型---值类型与引用类型(下)-应用征途》我们再见。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |