The choice between classes and structures

A C # msdn article called Choosing Between Classes and Structures gives the following advice:

Consider defining a structure instead of a class if the type instances are small and usually short-lived or are usually embedded in other objects.

Do not define a structure unless the type has all of the following characteristics:

It logically represents a single value, similar to primitive types 

(integer, double, etc.).

 It has an instance size smaller than 16 bytes. It is immutable. It will not have to be boxed frequently. 

If one or more of these conditions are not met, create a type link instead of a structure. Failure to follow this guide may adversely affect performance.

Interestingly, the answer will be in case D. Until now, I just used structures in all cases when I do not need polymorphism. I do not know if the size depends. Or something else.

+6
source share
4 answers

I would say that this advice definitely does not apply to D.

Structures are value types. Classes are reference types. Structures are usually on the stack (although they can be on the heap and indicated by pointers). Classes are on the heap. Structures do not have inheritance or polymorphism. Classes have inheritance and polymorphism.

Structures in D. are very often used. I believe that the general rule is that if something does not need to have polymorphism, it should be a structure. The main reason for choosing a class over a structure is because you want to inherit polymorphism as well.

The second reason may be that if the type has a type of a reference type, it is more appropriate (for example, the container should probably be a class, because copying it every time you pass it to the function will not be good), Structures may have reference semantics but it is just pure to use classes for this.

And finally, if the type contains a lot of data, and you don’t need to have a copy of it every time you pass it to a function, then it would be more efficient to make it a class and only copy it when you really need to (although you can just simply pass it instead of ref).

Structures

D is definitely more interesting than C # structures, since they have destructors and post-dense constructors . There is also no problem with auto-boxing in D, since D uses templates (similar to C ++, although much more powerful and much easier to use), rather than generics. And if you need a pointer to a structure, this is easy to do. So, I really don't think the tip for C # is related to D.

It seems to me that C # tips stem from two problems:

  • The fact that structures are types of values ​​and therefore have semantics of values.
  • The fact that C # structures must deal with autoboxing and be very concerned about the cost of copying.

Structures are also value types in D, but they are powerful enough to be able to use referential semantics if you want, and adding postblit constructors and destructors makes them much more useful than what you can do with structures in C #. And since D does not have autoboxing, concerns about autoboxing do not apply to D. You still do not want your structures to be huge, because if you do not follow the link, they will be copied whenever you pass them to a function but it is definitely not as important as in C #. This is much more consistent with C ++ in this regard.

And immutability advice doesn't apply at all to D. D structures that change frequently, and that would be a big problem if they weren't. For example, ranges are usually implemented as structures, and this is not possible if you cannot mutate them.

So no, I don’t think the C # advice really applies to D. The situation between the two languages ​​is too different. It would be better to think of D-structures as C ++ - classes that do not have base classes and cannot be obtained, since this is much closer to what they actually are than C # structures.

+7
source

There are several key differences from C # in D that make using struct more idiomatic:

  • There is no auto-boxing, because the problems that it solves are usually solved with the help of templates.

  • The garbage collector is currently less efficient.

  • Pointers to structures work well in most cases if you need reference semantics. (The only significant exception is that pointers to structures with overloaded arithmetic or index operators behave strangely, because operations are treated as pointer arithmetic instead of invoking operator overloads.) In addition, structures can be easily distributed across bushes using the new operator.

  • Structures can have deterministic destructors (not finalizers), copy constructors, etc., so you can do similar kinds of magic with them, as in C ++.

I would say that the structure should be used at any time when you do not need polymorphism, and it will not be needed in the future and does not need reference semantics, or if you need deterministic destruction, creating a copy, etc. If you need polymorphism, then you definitely need to use a class.

If you do not need polymorphism, but it requires reference semantics, then either the pointer to the structure selected by the heap or the final class will work well. The final class is a little better syntactically and does not fall into strange angular cases when overloading arithmetic operators. The structure avoids several bytes of overhead without having a vtable or monitor. If none of them is important to you, it's just a matter of personal preference.

+8
source

structs are passed by value, so size is really a consideration (although you can avoid this with ref and in )

basically you should use structs when you need to pass only by value (changes in the object should not be propagated), or it is a short object whose service life is short enough to stay on the stack (for example, see in the std.algorithm module, all functions there almost all return struct)

I personally defined structures for data objects (a sentence with a single value) as a 2d-point, and an angle with some convenient functions and operator overloading defined for them

+1
source

The same recommendations are generally applicable to D, as in C # - these are almost the same concepts.

The only exception is the recommendation on boxing - it does not apply, since boxing does not really exist initially in D.

0
source

Source: https://habr.com/ru/post/893948/


All Articles