If everything in C# inherits from Object, why aren’t all types by reference?

Asked

Viewed 107 times

5

If, for example, a struct type inherits from the class System.ValueType (who inherits from System.Object), why it, and the other types by value, are not allocated in the heap?

By making a Boxing, we do not use the operator new, how our type by value is allocated in the heap?

  • The question is not of beginner, she is good.

1 answer

4


Because they don’t need to be :) There are reasons for efficiency for some types to be by value.

Inheritance is something a little misunderstood and the fact that Object and ValueType being classes gives a slightly different indication of what these classes really are.

I am sure that if the interfaces allowed implementation in the methods as allowed 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 unique type that everyone derives from, not to take a ready-made structure, but to take capabilities that all objects must have. Object and ValueType only lend capabilities to 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.

You 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 without specific utility. There are contracts and behaviors defined in them, but not state, and without state of 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 in the interface did not allow implementation that has inside it.

Good to read Difference between type inheritance and implementation inheritance.

Use of the heap

Allocate into heap costs expensive (in fact the most problem is the release of the object when no longer needed), puts pressure on the Garbage Collector, takes up more space to manage allocation, it is more complicated to access, whenever you can avoid it is good to do.

Even when you’re gonna allocate a guy to heap because it will be inside another object is bad if it has a indirect when it is too simple. This is one of the problems of Java using a lot of memory and in some cases not being able to be as fast.

Today some people consider that C# should allow to say whether it will heap or in the stack, but in fact it would complicate the use of language a little, even though it would give more control. It is a shame that all class-based reference types are placed on the heap (today has type by reference allocated in the stack, but has limitations because it is 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 some other reason), then the only way to access it, the way it was implemented, is to turn the object into an object by reference, who is the one from Boxing, language can alone do this to you, and you have an inefficiency without realizing.

Value types have not been well implemented in C# (it’s not easy better than this without complicating the language), it’s just no worse than Java that neither has (nor had). They help a lot and in most situations, carefully, they are great and you see no flaws, but when they do, they can be invisible.

One of the great problems of Boxing is he make a new on your own, you don’t see what’s going on. But there are tools that help by telling you when it happens. Harder when the Boxing occurs in a more internal function, i.e., it is not your code that makes the Boxing, is the other component you consumed that makes.

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

The Boxing exists precisely because a type by value does not have the same internal structure of 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 if all possession by reference then there would be no Boxing. The specific phenomenon does not, but is that everything would already be boxed, you would not have any optimization in all situations.

Good to read Memory allocation in C# - Value types and reference types and What’s the difference between Struct and Class?.

Browser other questions tagged

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