What’s the difference between Struct and Class?

Asked

Viewed 19,312 times

68

What’s the difference between Struct and Class?

What kind of situation should I use Struct instead of a Class?

  • 6

    This question my http://answall.com/questions/14490/alocacao-de-memoria-em-c-typos-value_typos-referencedis about value types and reference types and this http://answall.com/questions/15510/o-que-imutavel-reallymeaningis about immutability. I think seeing the two you’ll understand the difference.

1 answer

75


Summary

  • Structs are types by value (Section 11.3.1).
  • All kinds struct implicitly inherit from the class System.ValueType (Section 11.3.2).
  • Assignment to a variable of type struct creates a copy of the value being assigned (Section 11.3.3).
  • The default value of a struct is the value produced after assigning all types values to their default value and all reference types for null (Section 11.3.4).
  • Operations of Boxing and Unboxing are used to convert between a type struct and an object (Section 11.3.5).
  • The meaning of the keyword this is different for structs (Section 11.3.6).
  • It is not allowed that instance field declarations for a struct include variable initializers (Section 11.3.7).
  • One struct cannot declare an instance constructor without parameters (Section 11.3.8).
  • One struct cannot declare a destructor (Section 11.3.9).

This summary is a translation of microsoft documentation and was carried out by mgibsonbr. But he had his reasons to remove the posted answer. I put here because it is a way that helps users.

Detailing

Struct

Structs are used to create data structures whose instances (objects) are small (in maximum 16 bytes), are immutable, represent a unique value, that is to say, it does not contain several characteristics, and does not need to be encapsulated (Boxing) in objects by reference frequently. These structures have their integral content (their value) copied when you need to transport from one location to another. So they are types by value (value types).

Copy of values

The fact of all members to be copied facilitates its use in concurrent environments. There is assurance that an instance will be accessed exclusively by thread that is running. Just be careful with structs containing references within it. The referenced objects are not "protected" against concurrent access. A struct is not safe in concurrent environment just because it is a struct, depends on how it was defined by the programmer. Atomicity, for example, is not intrinsically guaranteed.

Inheritance

Moreover, structs do not allow inheritance, although a struct is always implicitly derived from a class called ValueType which in turn is derived from another class Object as any kind in the CLR.

What do you mean, a struct is derived from a class? Yes, ValueType is an abstract class and Object only contains behavior and not state. There is nothing strange about it, these classes are only part of the hierarchy of type. So is doing subtype but not subclass. It’s like I’ve inherited only one interface.

There is nothing that obliges any type by value to be inherited only by types by value, in fact this is not even possible. Of course, if there was a state it would be more complicated, after all the state would have to be stored somewhere and it is expected to be accessed by a reference. In the case without state the reference does not matter. Only the behavior is inherited by type by value, that is, the type by value can directly call a method defined and/or implemented in these higher classes, nothing more than this, it does not receive state.

Inheritance indicates only one form of "is one" relationship between the basis and the derivative and does not imply change in the form of the storage (by reference or by value) of the state that will be defined by the derived structure. Obviously the derivative cannot have less than the basis.

Other limitations

  • One struct cannot have a constructor without parameters (called default) (Now you can). In practice there is a default constructor, but the programmer cannot define it on his own in C# (this is not true for CLR and other languages that can use otherwise. This needs to be understood when doing interoperability with languages other than CLR). read more in this answer.

  • When an object (an instance) struct is created, its value needs to be initialized always. Initialization takes place through the default values of all members of the struct.

  • Also have no destroyers. One struct is destroyed when it goes out of scope, when it is no longer needed as a local variable, or when another object contains the struct is destroyed.

Where they are used

As structs existing on . NET give an idea of how these types should define data with a unique feature, should represent a unique datum. Examples: int, double, bool, Decimal, DateTime.

The latter shows that simple information may have parts, in this case the date and time, but it is still a single data. Different from a calendar that has several related information. Calendar is a class and not a struct.

Class

Classes are used for all cases that a struct can cause problems, especially when they do not meet the above recommendations. And they are much more common in applications.

Avoid copying

It is common for you to have objects that have several characteristics and are therefore larger. As objects are large, making copies can become very costly in terms of processing, can waste memory and put pressure on Garbage Collector, so these objects are usually changeable, ie, they can have their features changed individually.

In mutable objects it is normal that only the reference is copied. In this case, are types by reference (Reference types). Nothing prevents a class or other type by reference from being set to work with immutable objects. The class String is the greatest example of this.

The destruction of a Reference type is made by Garbage Collector.

Its value default is null which is an invalid memory address.

Boxing

A type by reference, as is the case for a class, can be used to box a type by value (Boxing), creating a reference to its value. This technique should be avoided as much as possible. The creation of generic types allowed this type of operation to be largely avoided.

Roughly speaking this is done:

class BoxedInt {
    int value;
    public BoxedInt(int v) { this.value = v; }
    public int Unbox() { return this.value; }
}

So the code:

int i = 1;
object obj = i;  
int j = (int)obj;

would be converted to:

int i = 1;
object obj = new BoxedInt(i);
int j = ((BoxedInt)obj).Unbox();

I put in the Github for future reference.

Terminology

To understand some concepts presented here, you can consult other answers on the subject: immutability and Reference types vs value types which are concepts that are confused with classes and structs, respectively. The terms are not enough to be interchangeable since a class is not the only way to create a Reference type, there are the delegates and interfaces for example, and beyond the struct there is the value type enum.

Abuse of struct

It is common for inexperienced programmers to give preference to structs thinking that they are optimizing something, when, in fact, the result may be the other way around. In addition, without taking care to follow the recommendations described above, it is common to have problems using these types. We should only choose to create a struct when there’s a good reason for this.

Note that recommendations have been described for what should be a struct. Microsoft itself violates them in several examples within the .NET. Recommendation is not a mandatory rule. You can escape these characteristics when you know what you’re doing and have a good reason for it. These features are expected by programmers when using a struct defined, so if there is a good reason not to follow them this needs to be well documented.

It is not easy to understand the implications of a type by value

Although I can do it in one struct almost everything a class can, one should avoid complex situations that may not be so orthogonal or that can be misunderstood. The value copy concept is simple for simple operations, but becomes complex when you insert resources that don’t fit well into this type of data, creating traps. An event, for example, is undesirable.

structs are very useful, can optimize code and give the correct semantics, but they are not absolutely necessary. Java itself has lived without them until today (of course some operations are not tragic in performance because the language has primitive types that in the background have the same characteristic of a struct of C#). If the programmer cannot understand all the implications of a struct it is likely that it is better to opt for a class. It is not ideal, but it is the lesser evil.

Characteristic Struct Class
Type by reference or value value reference
Can have nested types (Enum, class, etc.) Yes Yes
May contain constants Yes Yes
May have fields Yes Yes
Fields can be initialized automatically Not Yes
Can have properties, indexers and methods Yes Yes
May have events Yes Yes
May have static members Yes Yes
Allows inheritance No (inherited from Valuetype) is always sealed Yes
Allows implection of interfaces Yes Yes
Can overlap constructors and operators Yes Yes
Allows setting default constructor Not Yes
You can use Generics Yes Yes
May be partial Yes Yes
Implementation of this variable with the value read-only reference
use of the new operator optional obligatory
  • In the following passage a question arose ? " But the behavior is only inherited by type by value, that is, the type by value can call a method defined and/or implemented in these upper classes.". Why types by references cannot call methods of higher classes assuming that there is inheritance between them ?

  • @Diegofarias I edited to try to make it clearer. There was a mistake and then became even more confused.

  • So a reference is only important to access the state of the objects ? Because the behavior I can access without having a reference directly.

  • @Diegofarias No, the reference is important whenever the object does not meet the criteria of the 1st. paragraph of the detailing. There are exceptions, but the basic rule is this. Don’t forget to read the 2 links you have in the terminology section. I do not know if you have read the post until the end, I show that the types by reference are very useful and if the person is in doubt which to use, it is better to avoid the type by value, although it is better in many cases. Choosing a type by value by mistake can cause problems.

  • 1

    I’m reading all the posts until the end, however, I get a little lost with so much information, but I’m rereading to try to understand better. I also saw that you say that beginner programmers use a lot of structs without knowing the concept of the object. I’ve done it myself. Today I’m using more classes.

  • @Diegofarias goes slowly, it’s a lot of information. And if you still have any questions that have been missing some details, you can ask a new question.

  • Maniero, in the table at the end of the answer says that using the new is optional. But when I removed the new and left the code that way MyStruct myStruct = MyStruct("something"); the compiler generated an error and only worked with the use of the new.

  • Yes, in fact it got weird, I need to make this clear, it is optional in the sense that it has syntax not to use, not that it can simply call the constructor without it and it works, only that some cases do not need to call the constructor.

Show 3 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.