Object #
object
(an alias for System.Object
) is the base class for all types. Every type can be upcast to this type. object
itself is a reference type - however, value types also inherit from it, thanks to the unified type system. This is not a perfect solution, though.
Boxing #
Casting a value type to/from an object
involves a so-called boxing/unboxing operation. Downcasting requires an explicit cast; if it fails, the Runtime throws an InvalidCastException
. The boxing operation consists of allocating the value type on the heap and copying it there. This is a costly operation and should be avoided if possible. Unboxing consists of copying the value type back to the stack.
int num = 42;
object obj = num; // Boxing
int unboxedNum = (int)obj; // Unboxing
Definition of the object
type
#
The definition of this type in the standard library looks as follows. Methods marked as virtual
are intended to be overridden in derived classes.
public class Object
{
public Object();
public extern Type GetType();
public virtual bool Equals(object obj);
public static bool Equals(object objA, object objB);
public static bool ReferenceEquals(object objA, object objB);
public virtual int GetHashCode();
public virtual string ToString();
protected virtual void Finalize();
protected extern object MemberwiseClone();
}
Methods in the object
type
#
Since all types inherit from object
, the methods (e.g., ToString()
, GetType()
, GetHashCode()
, and Equals(object)
) defined in object
are also available in other types. Calling these methods (except for GetType
) on a value type does not cause a boxing operation.
int i = 15;
Console.WriteLine(i.ToString());
Console.WriteLine(i.GetType());
Console.WriteLine(i.GetHashCode());
Console.WriteLine(3.Equals(i));
ToString
#
The ToString
method returns a string representation of the object. All built-in types override it. If a type did not override it, then ToString
returns the type name. You can override this method as follows:
Person alice = new Person {Name = "Alice", Age = 30};
Console.WriteLine(alice); // Alice, 30
class Person
{
public string Name;
public int Age;
public override string ToString() => $"{Name}, {Age}";
}
GetType
and the typeof
operator
#
The typeof
operator allows you to obtain type information at compile time, while the GetType
method does so at runtime. Apart from that, both methods work identically: they return an object that is a representation of the type.
DateTime now = DateTime.Now;
Console.WriteLine(now.GetType()); // evaluated at runtime
Console.WriteLine(typeof(DateTime)); // evaluated at compile time
Console.WriteLine(typeof(DateTime) == now.GetType());