2011-07-30 61 views
6
之间进行选择

在C#中的MSDN文章名为Choosing Between Classes and Structures给出了以下建议:类和结构

考虑定义一个类的结构,而不是如果 类型的实例是小的和普遍短命或通常是嵌入 其他对象。

不要定义的结构,除非该类型具有以下所有 特征:

It logically represents a single value, similar to primitive types 

(整数,双,和等等)。

It has an instance size smaller than 16 bytes. 

It is immutable. 

It will not have to be boxed frequently. 

如果这些条件的一个或多个不满足,创建参考 型代替的结构。如果不遵守这一指导方针, 会对性能产生负面影响。

我不知道D的答案会是什么。到目前为止,我只是在所有不需要多态性的情况下使用了结构。我不知道大小是否也是一个考虑因素。或其他任何东西。

+1

你说的是编程语言D吗?如果是这样,你正在谈论的是与C#完全不同的语言 - 开始尝试将来自一种语言和平台的推荐应用到另一种语言是一个非常糟糕的主意。 –

+3

@John Skeet--这不就是他问这个问题的原因。他阅读了关于适用于C#的东西,并询问D的情况是怎样的。 – iandotkelly

+0

@Jon Skeet。是的,我正在谈论D.对于混淆抱歉。我意识到,语言是不同的,这只是让我想知道。 – fwend

回答

7

我会说,这个建议肯定不会适用于D.

结构是值类型。类是引用类型。结构通常在堆栈上(尽管它们可以在堆上,并用指针指向)。类在堆上。结构没有继承或多态性。类具有继承性和多态性。

这是非常在D中使用结构是很常见的。我认为一般规则是,如果某些东西不需要有多态性,它应该是一个结构。 主要原因在结构上选择一个类的原因是因为你想要继承和多态。

第二个原因是,如果它只是更有意义的类型是一个引用类型(例如一个容器应该可能是一个类,因为每次你将它传递给一个函数时复制它不会很好)。结构可以有引用语义,但它只是使用类更清洁。最后,如果一个类型中包含大量数据,并且只要将它传递给一个函数就不需要它的副本,那么使它成为一个类并且只有它是更有效的当你真的需要时复制它(尽管你可以选择总是通过ref来代替它)。

D的结构比C#的结构更加奇特,因为它们具有析构函数和postblit constructors。 D中也没有自动装箱问题,因为D使用模板(类似于C++,尽管功能更强大,使用也更容易),而不是泛型。如果你需要一个指向结构的指针,很容易做到。所以,我真的不认为对于C#的建议适用于D.

在我看来,在C#建议从两个问题源于:

  1. 该结构是值类型,因此有事实价值语义。
  2. C#中的结构必须处理自动装箱并且必须非常担心复制的成本。

结构是也是d值类型,但他们足够强大,能够有引用语义,如果你想,并增设postblit构造函数和析构函数,使他们远比更有用什么你可以用C#中的结构来完成。而且由于D没有自动装箱,所以对自动装箱的担心不适用于D.你仍然不希望你的结构变得庞大,因为除非你通过ref,否则当它们通过时它们会被复制到一个函数,但它绝对不像在C#中那么大。在这方面它更符合C++。

而关于不变性的建议不适用于在所有到D. D结构经常是可变的,如果它们不是,它将是一个大问题。例如,范围通常是作为结构实现的,如果你不能改变它们,这是不可能的。

所以,不,我不认为C#的建议真的适用于D.这两种语言之间的情况完全不同。将D的结构看作没有任何基类并且不能派生的C++类会更好,因为它比C#的结构更接近实际的结果。

+0

结构具有引用语义不需要Post-blit构造函数。一个.net结构包装一个可变引用类型的私有字段,该类型只能在其构造函数中设置,通常会显示引用语义,无论是否需要它,因为该结构的副本将引用与原本的。我希望postblit构造函数的目的是允许一个结构保存对堆对象的唯一引用,以便能够直接更改该对象,而不是构造一个不同于所需方式的新对象。 – supercat

1

结构是按值传递这样的尺寸的确是一个考虑因素(尽管能避免与refin

大多是当你需要按值传递只(更改对象不该你应该使用结构”或者它是一个短寿命的对象,它的寿命足够短,可以保留在堆栈上(就像在std.algorithm模块中看到的范围对象;所有函数几乎全部返回一个结构)

个人I定义了数据对象(单值子句)的结构,如2d点和一些带有一些便利功能和操作符超载的角度ng为他们定义

0

相同的建议一般适用于D在C#中 - 他们几乎是相同的概念。

唯一的例外是拳击建议 - 它并不适用,因为拳击并没有真正原生的D.

8

在d存在的,也有从C#,使得它的几个关键差异习惯使用struct更频繁:

  1. 有没有自动装箱,因为它解决的问题通常与模板解决。

  2. 现在,垃圾收集器效率较低。

  3. 如果您想要引用语义,大多数情况下指向结构体的指针都可以很好地工作。 (唯一的一个主要例外是指向具有重载算术或索引操作符的结构的指针表现异常,因为这些操作被视为指针算术而不是调用操作符重载。)此外,可以使用new运算符轻松地为堆分配结构。

  4. 结构可以有确定性的析构函数(不是终结器),复制构造函数等,所以你可以用C++做类似的魔术。

我想说一个结构应使用任何时候你不需要多态性,不会需要它的未来,不需要引用语义,或者如果你需要确定的破坏,拷贝构造,等等。如果你需要多态,那么你肯定需要使用一个类。

如果您不需要多态但希望引用语义,那么指向堆分配结构或最终类的指针都可以正常工作。最后一个类在语法上稍微好一点,并且在重载算术运算符时不会碰到怪异的角落情况。通过没有vtable或监视器,结构可以避免几个字节的开销。如果这些都不重要,那么这只是个人喜好的问题。