在类和结构之间进行选择

时间:2011-07-30 17:42:08

标签: class polymorphism d struct

关于名为Choosing Between Classes and Structures的C#的msdn文章给出了以下建议:

  

如果是实例,请考虑定义结构而不是类   类型很小,通常是短暂的或通常嵌入   其他对象。

     

除非类型具有以下所有内容,否则不要定义结构   特性:

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的情况下答案是什么。到目前为止,我只是在所有不需要多态的情况下使用结构。我不知道尺寸是否也是一个考虑因素。或其他任何事情。

4 个答案:

答案 0 :(得分:8)

在D中,与C#存在一些主要差异,因此更频繁地使用struct

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

  2. 目前,垃圾收集器的效率较低。

  3. 如果您想要引用语义,在大多数情况下指向结构的指针都可以正常工作。 (唯一的例外是指向带有重载算术或索引操作符的结构的指针表现得很奇怪,因为操作被视为指针算术而不是调用操作符重载。)此外,可以使用new运算符轻松地对结构进行堆分配。

  4. 结构可以有确定性的析构函数(不是终结符),复制构造函数等,所以你可以像在C ++中那样用它们做类似的魔术。

  5. 我会说在任何时候你不需要多态而且以后不需要它而且不需要引用语义,或者你需要确定性破坏,复制构造等等时应该使用结构。如果你需要多态性然后你肯定需要使用一个类。

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

答案 1 :(得分:7)

我会说这个建议确实适用于D.

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

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

第二个原因是,如果它更适合作为引用类型的类型(例如,容器应该是一个类,因为每次将它传递给函数时复制它都不会很好) 。结构可以具有引用语义,但使用类更简洁。

最后,如果一个类型中包含大量数据,并且每次将它传递给函数时都不需要复制它,那么将它作为一个类并且只复制它会更有效当你真正需要时(尽管你可以选择总是通过ref传递它)。

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

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

  1. 结构是值类型,因此具有值语义。
  2. C#中的结构必须处理自动装箱这一事实,并且必须非常担心复制的成本。
  3. 结构也是D中的值类型,但是如果你愿意的话,它们足够强大,能够有引用语义,并且postblit构造函数和析构函数的添加使它们对更有用比你在C#中使用结构可以做什么。由于D没有自动装箱,因此对自动装箱的担忧不适用于D.你仍然不希望你的结构很大,因为除非你通过参考,否则每当你通过它们时它们都会被复制一个函数,但它绝对不像C#中那么大。在这方面,它更符合C ++。

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

    所以,不,我不认为C#建议真的适用于D.两种语言之间的情况太不同了。最好将D的结构视为C ++类,它们没有任何基类,也不能从中派生出来,因为它比C#的结构更接近实际的结构。

答案 2 :(得分:1)

结构通过值传递,因此大小确实是一个考虑因素(尽管可以通过refin来避免这种情况)

当你需要仅传递值时(对象的更改不应传播),或者它是一个短命的对象,它的生命周期很短,可以保留在堆栈上(就像你的'一个范围对象')。 ll在std.algorithm模块中看到;那里的所有函数几乎都返回一个struct)

我个人已经定义了数据对象的结构(单值子句),如2d点和角度,带有一些便利函数和为它们定义的运算符重载

答案 3 :(得分:0)

同样的建议通常适用于D和C#中的相同 - 它们几乎是相同的概念。

唯一的例外是拳击推荐 - 它不适用,因为拳击在D中本身并不存在。