值类型数据还是引用类型数据?结构还是类?什么你须要使用它们呢?这不 是C++,你可以把所有类型都定义为值类型,并为它们做一个引用。这也不是 Java,所有的类型都是值类型。你在创建每个类型实例时,你必须决定它们以什 么样的形式存在。这是一个为了取得正确结果,必须在一开始就要面对的重要决 定。(一但做也决定)你就必须一直面对这个决定给你带来的后果,因为想在后 面再对它进行改动,你就不得不在很多细小的地方强行添加很多代码。当你设计 一个类型时,选择struct或者class是件简单的小事情,但是,一但你的类型发 生了改变,对所有使用了该类型的用户进行更新却要付出(比设计时)多得多的工 作。
这不是一个简单的非此及彼的选择。正确的选择取决于你希望你的 新类型该如何使用。值类型不具备多态性,但它们在你的应用程序对数据的存取 却是性能有佳;引用类型可以有多态性,并且你还可以在你的应用程序中为它们 定义一些表现行为。考虑你期望给你的类型设计什么样的职能,并根据这些职能 来决定设计什么样的类型。结构存储数据,而类表现行为。
因为很多的 常见问题在C++以及Javaj里存在,因此.Net和C#对值类型和引用类型的做了区分 。在C++里,所有的参数和返回值都是以值类型的进行传递的。以值类型进行传 递是件很有效率的事,但不得不承受这样的问题:对象的浅拷贝(partial copying)(有时也称为slicing object)。如果你对一个派生的对象COPY数据时, 是以基类的形式进行COPY的,那么只有基类的部分数据进行了COPY。你就直接丢 失了派生对象的所有信息。即使时使用基类的虚函数。
而Java语言呢, 在放弃了值类型数据后,或多或少有些表现吧。Javs里,所有的用户定义类型都 是引用类型,所有的参数及返回数据都是以引用类型进行传递的。这一策略在( 数据)一致性上有它的优势,但在性能上却有缺陷。让我们面对这样的情况,有 些类型不是多态性的--它们并不须要。Java的程序员们为所有的变量准备了一个 内存堆分配器和一个最终的垃圾回收器。他们还须要为每个引用变量的访问花上 额外的时间,因为所有的变量都是引用类型。在C#里,你或者用struct声明一个 值类型数据,或者用class声明一个引用类型数据。值类型数据应该比较小,是 轻量级的。引用类型是从你的类继承来的。这一节将练习用不同的方法来使用一 个数据类型,以便你给掌握值类型数据和引用类型数据之间的区别。
我 们开始了,这有一个从一个方法上返回的类型:
private MyData _myData;
public MyData Foo()
{
return _myData;
}
// call it:
MyData v = Foo();
TotalSum += v.Value;
如果MyData是一个值类型,那么回返值会被COPY到V中 存起来。而且v是在栈内存上的。然而,如果MyData是一个引用类型,你就已经 把一个引用导入到了一个内部变量上。同时,
你也违犯了封装原则(见原 则23)。
或者,考虑这个变量:
private MyData _myData;
public MyData Foo()
{
return _myData.Clone( ) as MyData;
}
// call it:
MyData v = Foo();
TotalSum += v.Value;