If everything in C# inherits from Object, why are all types not by reference?

If, for example, a struct type inherits from the Class System.ValueType (which inherits from System.Object), Why is it, and the other types by value, not allocated in the heap ?

When doing a boxing , we don't use the new operator, how is our type by value allocated in the heap?

Author: Maniero, 2020-06-26

1 answers

Because they don't have to be:) there are efficiency reasons for some types to be by value.

Inheritance is something a bit misunderstood and the fact that Object and ValueType are classes gives a slightly different indication of what those classes actually are.

I'm sure if interfaces allowed implementation in methods as it has since C# 8, these types would be interfaces and not classes (actually it would need to be a little different than what was implemented in the language, but it was implemented with limitations because of compatibility, at first it could get more powerful).

Classes define objects, interfaces define, and now implement, capabilities. So it's interesting to have a single type that everyone derives, not to take a ready-made structure, but to take capabilities that all objects should have. Object e ValueType they only lend capabilities to the objects, so they could be interfaces, you just need these types to indicate a contract and eventually a standard implementation of some methods to not force all types to implement something.

Can see in their source (linkei above) that there is no structure (States), if you inherit from it and do not add something extra you will have an object with no specific utility. There are contracts and behaviors defined in them, but no state, and without state in fact we do not have a functional object.

The case of Object even has an extra reason to exist as a class, you can use this type to create a real object without determining what it is, but it has little value and has other solutions to it if it turned interface. The case of ValueType has zero reasons to be a class, so much so that it is abstract, had reason at the time of 1.0 because the interface did not allow implementation that has inside it.

Good to read difference between type inheritance and implementation inheritance .

Using heap

Allocate no heap is expensive (in fact the problem more is the release of the object when it does not need more), puts pressure on the garbage collector, takes up more space to manage the allocation, is more complicated to access, whenever you can avoid this is good to do.

Even when it will allocate a type in the heap because it will be inside another object it is bad if it has a indirection when it is too simple. This is one of the problems of Java using a lot of memory and in some cases fail to be as fast.

Today some people consider that C# should allow to say whether it will allocate in the heapor in the stack, but in fact this would complicate the use of the language a little, despite giving more control. It's a shame that all class-based per-reference types are placed in the heap (today it has per-Reference Type allocated in the stack , but it has limitations for being a struct).

Boxing

One of the problems with this optimization is that if you have a context that expects an object to be by reference (because of polymorphism or other reason), then the only way to access it, the way it was implemented, is to turn the object into an object by reference, which is the same as the boxing, the language can do that for you alone, and you have an inefficiency without realizing it.

Types by value were not well implemented in C# (Not Easy better than that without complicating the language), just no worse than Java that neither has (or did not have). They help a lot and in a good part of the situations, with care, they are great and you do not see defects, but when they have, they can be invisible.

One of the big problems of boxing is it doing a new on its own, you don't see what's going on. But it has tools that help by saying when it happens. Harder when the boxing occurs in a more internal function, that is, it is not your code that does the boxing, it is that of another component that you consumed that does.

In many codes none of this matters, but if you need maximum performance you have to be very careful.

boxing exists precisely because a type by value does not have the same internal structure as a type by reference. A type by reference that goes in the heap always has a hidden internal state and that language treats in a special way. See more in what is the minimum size of an object in memory?.

You think that if all possession by reference then there would be boxing. The specific phenomenon is not, but it is that everything would already be boxed, you would not have any optimization in all situations.

Good Read memory allocation in C# - Value Types and reference types and What is the difference between Struct and Class?.

 4
Author: Maniero, 2020-06-29 14:17:54