10

These are the docs about .ToString() that has prompted this question. They state:

Because Object is the base class of all reference types in the .NET Framework, this behavior [.ToString()] is inherited by reference types that do not override the ToString method.

Yet further on it goes to state:

For example, the base types such as Char, Int32, and String provide ToString implementations

However Int32 is a struct and hence must be a value type.

So what's going on here? Does Int32 implement it's very own .ToString() which has nothing to do with Object?

m.edmondson
  • 30,382
  • 27
  • 123
  • 206
  • 2
    I am pretty sure it has to do with boxing. – MBen Nov 16 '11 at 13:57
  • http://forums.asp.net/t/1694055.aspx/1?Reference+types+and+Value+types+Inheritance+from+Object+class –  Nov 16 '11 at 13:58
  • 1
    @MBen I am pretty sure the question and answer have nothing to do with boxing. – Ben Robinson Nov 16 '11 at 14:00
  • It sounds like maybe you are confused about how it is that a value type can inherit from a reference type, which is a bit like being confused about how you can put a red box inside a blue box -- surely you can only put blue boxes inside other blue boxes, right? No, you can put a red box in a blue box, and you can derive a value type from a reference type too. This might help: http://blogs.msdn.com/b/ericlippert/archive/2011/09/19/inheritance-and-representation.aspx – Eric Lippert Nov 16 '11 at 14:31
  • 1
    Note that the documentation that you quote says that "`Object` is the base class of all reference types in the .NET Framework." However, this does NOT imply that everything that has `Object` in its inheritance hierarchy is a reference type. (All cats are in the class *Mammalia* but not all species in the class *Mammalia* are cats.) It is perfectly legal for a value type to inherit from a reference type, and in fact, all `struct` derive from `ValueType` (itself a reference type)` and `ValueType` derives from `Object`. – jason Nov 16 '11 at 14:35

6 Answers6

13

Int32 is a struct and therefore a value type. But:

System.Object
   System.ValueType
      System.Int32

Int32 derives from System.ValueType and this itself derives from System.Object. Et voilà...

Anja
  • 324
  • 1
  • 2
  • 1
    have you ever seen a struct-declaration like `public struct Foo : System.Object`...? i am wondering how they get this to compile :) if you ever decompile `System.Int32` you'll get `public struct Int32 : IComparable, IFormattable, IConvertible, IComparable, IEquatable` ... but still having a baseType `System.ValueType`... strange, isn't it? –  Nov 16 '11 at 14:00
  • 1
    Excellent this helped me to understand - so is there something special about `System.ValueType` that makes the runtime handle it differently? – m.edmondson Nov 16 '11 at 14:10
  • @m.edmondson that is the part i've never understood neither ... i *guess* it is special by the clr ... i think the .net-clr-specification book from microsoft (sth like this: http://www.amazon.de/Programming-Language-Covering-Microsoft-Development/dp/0321741765/ref=sr_1_22?ie=UTF8&qid=1321453023&sr=8-22) will cover that magic :) –  Nov 16 '11 at 14:17
  • 1
    I think it would be handy is @Jon could elaborate on that! – m.edmondson Nov 16 '11 at 14:19
  • 1
    @AndreasNiedermair: What is it specifically that you are wondering about? I assure you that there's nothing magical about it; it's a straightfoward compiler. – Eric Lippert Nov 16 '11 at 14:33
  • 4
    @Andreas Niedermair: That's not legal per the specification. The specification spells out exactly that you can't explicitly derive from `System.ValueType` and that there's a special reserved word `struct` that accomplishes this, and that when you use it to mark a type definition, you can only list interfaces that the type implements but not a base class (again, it implicitly derives from `System.ValueType`). – jason Nov 16 '11 at 14:40
  • @EricLippert @Jason got it straight! ... the `struct` keyword implies `System.ValueType` ... thanks @Jason! –  Nov 17 '11 at 06:32
11

Yes, Int32 overrides ToString... although that's somewhat irrelevant here. All types inherit the members of object - you can always call ToString(), you can always call Equals etc. (ValueType overrides Equals and GetHashCode for you, although you should almost always override them further in structs to provide a more efficient implementation.)

Note that you can override the methods yourself very easily:

public struct Foo
{
    public override string ToString()
    {
        return "some dummy text";
    }
}

It's not clear which aspect is confusing you (there are quite a few different areas involved here). If you could clarify, we could address the specific issue.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    i guess he's confused with the fact, that value types behave like value types but inherit from object, which is a class and hence a reference type .. –  Nov 16 '11 at 13:59
  • 1
    @AndreasNiedermair: More than that, they inherit from `ValueType` which is itself a class :) – Jon Skeet Nov 16 '11 at 14:00
  • jup, know that, just wanted to get this very straight :) –  Nov 16 '11 at 14:01
  • Thanks Jon - it was _your_ article about value + reference types which made me start thinking about this. The confusion lies in the statement `Object is the base class of all reference types` and hence inherits `.ToString` so why does Int32 also inherit this? – m.edmondson Nov 16 '11 at 14:03
  • Being the base class for all reference types doesn't mean it cannot be in the inheritance hierarchy for all value types as well. – Domenic Nov 16 '11 at 14:04
  • see my comment @http://stackoverflow.com/questions/8152761/since-int32-is-a-value-type-why-does-it-inherit-tostring/8152830#8152830 –  Nov 16 '11 at 14:05
  • @m.edmondson, see [here](http://msdn.microsoft.com/en-us/library/system.valuetype.aspx) for the value type object hierarchy. – John H Nov 16 '11 at 14:07
  • @JonSkeet - So is there something special about `System.ValueType` that means the CLR treats it differently? – m.edmondson Nov 16 '11 at 14:20
  • @m.edmondson: Yes - the CLR knows about `System.ValueType` and `System.Enum`. They're very special types. – Jon Skeet Nov 16 '11 at 14:21
5

Perhaps you confusion arises from not realizing that value types inherit from Object? Here is the inheritance graph of System.Object, System.ValueType, System.Int32 and MyNamespace.Customer which is supposed to be a class of you own making. I was lazy and didn't write all the public methods and interfaces of Int32.

UML

ToString is declared in Object but is overriden both in ValueType and in Int32.

Martin Liversage
  • 104,481
  • 22
  • 209
  • 256
0

The docs are wrong. Both reference and value types inherit that behavior from object (but do remember that not everything in .NET is a class that derives from object).

All (most?) core value types override ToString() to return something more sensible than the class name.

Euro Micelli
  • 33,285
  • 8
  • 51
  • 70
  • 1
    The documentation quoted above is correct. Why do you believe it is incorrect? – Eric Lippert Nov 16 '11 at 14:34
  • 1
    @ERic Lippert: If value types inherit from ValueType, that would suggest one can use value types anyplace one may use ValueType. That doesn't work, though: ValueType satisfies a class constraint but not a struct constraint, whereas value types satisfy a struct constraint but not a class constraint. If one assigns a struct with a mutating interface (e.g. the `List` enumerator) to a variable of type `ValueType`, the resulting variable will behave as a mutable class type, rather than a mutable value type. – supercat Dec 17 '11 at 00:12
  • @supercat: There's a bit of a logical fallacy in your argument. If a struct S inherits from ValueType then one expects that (1) all members of ValueType are also members of S; that's the definition of "inheritance". And (2) that a value of type S may be assigned to a variable of type ValueType (in this case, via a boxing conversion). But those are both facts about *instances* of S. There is no requirement that *the type* S be usable everywhere that *the type* ValueType may legally be used. – Eric Lippert Dec 17 '11 at 03:42
  • 2
    @supercat: think about it this way: an apple is a kind of fruit. If you have a bowl that can contain fruit, then that bowl can contain an apple; apples are assignment-compatible with fruit. All fruit have a property "taste"; apples have that property because they are fruit. Apples inherit properties from fruit. But that does not mean that you can substitute *the word* "apple" everywhere that *the word* fruit appears and preserve the truth of a sentence! "The word 'fruit' begins with the letter 'f'" cannot be substituted with "apple" and preserve its truth. – Eric Lippert Dec 17 '11 at 03:45
  • @EricLippert: Conversion from an unboxed value type to ValueType is a representation-changing conversion. Conversion of a boxed value type to ValueType is representation-preserving. To my mind, that would suggest that "boxed value types" are effectively class-type objects that inherit from ValueType, but unboxed ones are not. Instead, they are implicitly convertible to boxed value types, which do inherit from ValueType. The wrinkle is that a request to JIT code which would work with a parameter, variable, or field that's derivative of ValueType... – supercat Dec 17 '11 at 17:50
  • @EricLippert: ...will produce code which manipulates the entity directly rather than via heap reference. As I think about it, I'm somewhat impressed with the .net 2.0 people who managed to make generics work as well as they do. It might be interesting to ponder how things might have worked if there had been a means for heap-reference objects to exhibit value semantics (meaning that a copy could not just be a blit, but would have to recursively copy any nested heap-references that were supposed to have value semantics), but that would have complicated things further. – supercat Dec 17 '11 at 17:54
  • @EricLippert: I guess my biggest confusion is how to describe the type of what's passed in to a parameter, to distinguish boxed value types from real value types. My inclination would be to regard variables/fields/parameters of value types as being outside the type system. Consider calling `bool f(T bar) where T:IEnumerator {return bar.MoveNext();}` with either a variable of type List.Enumerator, or a variable of type IEnumerator which holds a List.Enumerator. How would you describe the type of the instance passed in `bar` in each case? – supercat Dec 17 '11 at 17:58
  • @supercat: You are confusing *inheritance* with *assignment compatibility*. *Inheritance* is the property *of types* that members of a base type are also members of a derived type; inheritance has nothing to do with how the bits look in memory. An unboxed value type is not assignment-compatible with a variable of type ValueType, but the value type still inherits all the members of its base class. – Eric Lippert Dec 17 '11 at 18:25
  • @EricLippert: An unboxed value may be assigned to one of ValueType without an explicit typecast (though not vice versa). – supercat Dec 21 '11 at 00:10
0

I think the short answer to your question is that value types inherit from System.ValueType and that in turn inherits from object.

Ben Robinson
  • 21,601
  • 5
  • 62
  • 79
0

Every struct have inheritance from System.ValueType class (not allowed) which is done solely by the compiler. All struct have methods from ValueType base class which is inherited from Object class makes us have access to ToString() and all others.

Even though ValueType is inherited from Object class but it has special implementation of the overrides.

Abdul Munim
  • 18,869
  • 8
  • 52
  • 61