views:

470

answers:

3

C# doesn't allow structs to derive from classes, but all ValueTypes derive from Object. Where is this distinction made?

How does the CLR handle this?

+2  A: 

This is a somewhat artificial construct maintained by the CLR in order to allow all types to be treated as a System.Object.

Value types derive from System.Object through System.ValueType, which is where the special handling occurs (ie: the CLR handles boxing/unboxing, etc for any type deriving from ValueType).

Reed Copsey
+4  A: 

Small correction, C# doesn't allow structs to custom derive from anything, not just classes. All a struct can do is implement an interface which is very different from derivation.

I think the best way to answer this is that ValueType is special. It is essentially the base class for all value types in the CLR type system. It's hard to know how to answer "how does the CLR handles this" because it's simply a rule of the CLR.

JaredPar
+1 for the good point about structs not deriving from anything [except implicitly deriving from System.ValueType].
Reed Copsey
You say that `ValueType` is special, but it's worth mentioning explicitly that `ValueType` itself is actually a reference type.
LukeH
If internally it's possible for structs to derive from a class, why don't they expose it for everyone?
Joan Venge
@Joan, the problem is that it's not. The CLR simply doesn't allow this to happen and C# propagates this restriction
JaredPar
@Joan: They don't, really. This is just so that you can cast a struct to an object, and there for utility. But technically, when compared to how classes are implemented, value types are handled completely differently by the CLR.
Reed Copsey
Thanks I thought valuetypes derive from ValueType type which is a class?
Joan Venge
+10  A: 

C# doesn't allow structs to derive from classes

Your statement is incorrect, hence your confusion. C# does allow structs to derive from classes. All structs derive from the same class, System.ValueType, which derives from System.Object. And all enums derive from System.Enum.

Where is this distinction made?

It's made everywhere in the world that the compiler runs. :-)

Seriously, I don't understand the question. What do you mean by "where"?

How does the CLR handle this?

Extremely well. :-)

Again, I don't understand what you're asking. What makes a value type a value type is that its instances are copied by value. What makes a reference type a reference type is that its instances are copied by reference. You seem to have some belief that the inheritance relationship between value types and reference types is somehow special and unusual, but I don't understand what that belief is. Inheritance has nothing to do with how things are copied.

Look at it this way. Suppose I told you the following facts:

  • There are two kinds of boxes, red boxes and blue boxes.

  • Every red box is empty.

  • There are three special blue boxes called O, V and E.

  • O is not inside any box.

  • V is inside O.

  • E is inside V.

  • No other blue box is inside V.

  • No blue box is inside E.

  • Every red box is in either V or E.

  • Every blue box other than O is itself inside a blue box.

The blue boxes are reference types, the red boxes are value types, O is System.Object, V is System.ValueType, E is System.Enum, and the "inside" relationship is "derives from".

That's a perfectly consistent and straightforward set of rules which you could easily implement yourself, if you had a lot of cardboard and a lot of patience. Whether a box is red or blue has nothing to do with what it's inside; in the real world it is perfectly possible to put a red box inside a blue box. In the CLR, it is perfectly legal to make a value type that inherits from a reference type, so long as it is either System.ValueType or System.Enum.

So let's rephrase your question:

How do ValueTypes derive from Object (ReferenceType) and still be ValueTypes?

as

How is it possible that every red box (value types) is inside (derives from) box O (System.Object), which is a blue box (a reference Type) and still be a red box (a value type)?

When you phrase it like that, I hope it's obvious. There's nothing stopping you from putting a red box inside box V, which is inside box O, which is blue. Why would there be?

Eric Lippert
Thanks Eric. It makes sense now. Do you know why this functionality for structs to be able to derive from classes, etc isn't allowed for C# programmers?
Joan Venge
Language constructs should be meaningful. What would it *mean* to have an arbitrary value type derived from an arbitrary reference type? Is there anything you could accomplish with such a scheme that you could not also accomplish with user-defined implicit conversions?
Eric Lippert
I guess not. I just thought you could have some members available to many valuetypes that you see as a group, which you could do using an abstract class to derive the struct. I guess you could use implicit conversions but then you would pay performance penalty, right? If you are doing millions of them.
Joan Venge
Ah, I see. You want to use inheritance not as a mechanism for modeling "is a kind of" relationships, but rather simply as a mechanism for sharing code between a bunch of related types. That seems like a reasonable scenario, though personally I try to avoid using inheritance purely as a code-sharing convenience.
Eric Lippert
Thanks Eric. You are right. This isn't a deal breaker for me. And I am particularly careful not to overcomplicate structs because of performance reasons.
Joan Venge
Joan to define the behavior once, you can create an interface, have the structs you want to share behavior implement the interface then create an extension method operating on the interface. One potential issue with this approach is when calling the interface methods the struct will be boxed first and the copied boxed value will be passed to the extension method. Any change in state will happen on the copy of the object which may be unintuitive to users of the API.
David Silva Smith