int a = 2;
Console.WriteLine(a.ToString()); // displays 2
// definition of ToString() here - public override string ToString();
Now, here are some of my understandings:
ToString()
method, which is inherited from the Object
class.int
is a structure of type Int32
, which gets a couple of ToString()
[With Parameters] methods from the Interfaces which it implements.ToString()
[without params] function in struct Int32
According to http://msdn.microsoft.com/en-us/library/system.int32.tostring.aspx,
struct Int32 overrides ValueType.ToString() method
If a struct cannot inherit some class or struct, can you please explain how this ToString()
method is available for Int32
?
If a struct cannot inherit some class or struct,
This isn't true. All structs (and the built-in value types, like System.Int32
, System.Single
, etc) always implicitly inherit from System.ValueType
(which, in turn, inherits from System.Object
).
However, you can't make a struct that inherits from anything else.
This is clearly spelled out in the C# language spec, 4.1.1:
4.1.1 The System.ValueType type
All value types implicitly inherit from the class System.ValueType, which, in turn, inherits from class object. It is not possible for any type to derive from a value type, and value types are thus implicitly sealed (§10.1.1.2).
Then, later (4.1.3) struct is explicitly defined to be a value type:
4.1.3 Struct types
A struct type is a value type that can declare constants, fields, methods, properties, indexers, operators, instance constructors, static constructors, and nested types.
Int32
implements IFormattable
, which defines the ToString
method
Every definition of a type derived from ValueType actually defines two distinct kinds of things in the runtime: a type of heap object (which derives from ValueType
and in turn from Object
, and which contains embedded type information), and a type of storage location (which doesn't contain any embedded type information, but instead requires that code which uses it must have some other means of knowing what it is). An instance of the heap object type contains a field of the storage-location type, and code which attempts to access this
will access that field. If a value type is cast implicitly or explicitly to a storage location of reference type, the system will create a new heap object with the appropriate type and copy all public and private fields of the value-type to corresponding fields within the heap object. If a heap object is cast to a value-type storage location, all public and private fields from the heap object will be copied to the value-type storage location.
If an attempt is made to use any Object
or interface method on a heap object of a value type, the method will be called just like any other heap-object method. If the attempt is made on a value-type storage location, for any method other than GetType
, the compiler will generate a special "constrained" opcode which informs the runtime of the type of the storage location and instructs the Runtime to call the address of the method appropriate to that type. Since the compiler will have the storage location type available, and the run-time can use that to find the appropriate method, the appropriate method can be invoked directly on the storage location, without having to create a new heap object first. GetType
is the one notable exception; since it works by examining the type information embedded within an object, it can only work on things that have embedded type information. Consequently, its argument will be converted to the heap-object form before the call; GetType
will then be able to examine the embedded type information of that heap object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With