#950 – C# Has a Unified Type System

C# has a unified type system, which means that all types inherit, directly or indirectly, from object (System.Object).  This includes both reference and value types.  It also includes all primitive types, like int and bool, as well as every type provided in the .NET Framework and every custom type that you define.

Because every type inherits from object, you can call any of the System.Object methods (e.g. Equals and ToString) on an instance of any type.

            Dog d = new Dog("Bob", 5);
            int i = 42;
            bool awake = true;




#771 – Summary of System.Object Members

Every type inherits from System.Object, directly or indirectly, and therefore has access to its members.  Here’s a brief summary of all members of System.Object.

  • Object  constructor –  called when object is created, ultimately called for every object
  • Equals(object) – compares object to specified object; true for reference types if parameter references the current object  [virtual]
  • Equals(object,object) – static method to compare two objects
  • Finalize – called when the object is being destroyed  [virtual]
  • GetHashCode – is meant to provide a unique number used in hashing algorithms, but should be overridden so that value returned is unique based on object contents  [virtual]
  • GetType – returns the Type of the object
  • MemberwiseClone – Makes a copy (shallow) of the object by copying its members
  • ReferenceEquals(object,object) – static method to see if two references refer to the same object
  • ToString – returns a string that describes the object; by default, just returns the type name

#662 – Overriding the ToString Method for a Custom Type

Every type inherits a ToString method, since every type inherits, directly or indirectly, from System.Object.  For a custom type, this method will by default just display the name of the type.

Dog kirby = new Dog("Kirby", 13);


You can, however, override the ToString method in your class so that it provides information about the specific instance of the class.  In the example below, we override Dog.ToString.

    public class Dog
        public string Name { get; set; }
        public int Age { get; set; }

        public Dog(string name, int age)
            Name = name;
            Age = age;

        public override string ToString()
            return string.Format("Dog [{0}] is {1} years old", Name, Age);

#661 – Every Object Has A ToString Method

Since every type inherits either directly or indirectly from System.Object, and System.Object has a ToString method, every object inherits a ToString method.

The ToString method is intended to return a string identifying or representing the object, i.e. that specific instance.  This is true for both value types and reference types.

For built-in types, ToString generally returns what you’d expect.  For example, for a System.Int32 (int), it returns the value of the integer.

For custom types, if you don’t override ToString and provide something more meaningful, ToString just returns a string representing the type of the object.

Dog kirby = new Dog("Kirby", 13);
Cow bessie = new Cow("Bessie");
int i = 12;
double d = 1.38e-23;
DayOfWeek bestDay = DayOfWeek.Saturday;
object o = new System.Object();
DateTime dt = new DateTime(1536, 5, 19);

// ToString can be called explicitly, or is called
// implicitly when passing object as string parameter
Console.WriteLine(kirby.ToString());   // Explicit
Console.WriteLine(bessie);             // Implicit

#659 – Get Information About an Object’s Type

You can call the GetType method of System.Object on any object to get information about that object’s type.  Because every type in .NET inherits directly or indirectly from System.Object, every object will have access to the GetType method.

GetType returns an instance of a Type object, which can be queried to learn all about the type of the original object.

        static void Main()
            Dog kirby = new Dog("Kirby", 13);

            int i = 12;

        private static void DumpTypeInfoFor(object o)
            Type t = o.GetType();

            Console.WriteLine("Type = {0}", t);
            Console.WriteLine("  Assembly = {0}", t.Assembly);
            Console.WriteLine("  BaseType = {0}", t.BaseType);
            Console.WriteLine("  FullName = {0}", t.FullName);
            Console.WriteLine("  IsClass = {0}", t.IsClass);
            Console.WriteLine("  IsValueType = {0}", t.IsValueType);

            Console.WriteLine("  Properties:");
            foreach (PropertyInfo pi in t.GetProperties())
                Console.WriteLine("    {0}", pi.Name);

            Console.WriteLine("  Methods:");
            foreach (MethodInfo mi in t.GetMethods())
                Console.WriteLine("    {0}", mi.Name);

            Console.WriteLine("  Events:");
            foreach (EventInfo ei in t.GetEvents())
                Console.WriteLine("    {0}", ei.Name);

            Console.WriteLine("  Interfaces:");
            foreach (Type ti in t.GetInterfaces())
                Console.WriteLine("    {0}", ti.Name);

#401 – Every Object Inherits an Equals Method

Every type inherits directly or indirectly from System.Object, so each has an Equals method.  This includes both value types (which inherit from System.ValueType) and reference types (which inherit from System.Object).

            public virtual bool Equals(Object object);

The Equals method returns true if the object passed in to the method is equal to the object on which the method was called.

System.Object includes a default implementation of the Equals method that :

  • For value types, returns true if the underlying values are the same (even though there are two copies of the value)
  • For reference types, returns true if the references refer to the exact same object in memory
            float f1 = 10.2f;
            float f2 = 10.2f;
            bool sameFloat = f1.Equals(f2);     // true - same value

            Dog kirby = new Dog("Kirby", 13);
            Dog kirby2 = new Dog("Kirby", 13);
            bool sameDog = kirby.Equals(kirby2);   // false - two different objects

            Dog kirby3 = kirby;
            sameDog = kirby3.Equals(kirby);    // true - two references to same object

#332 – Every Class Inherits from Exactly One Class

Every class that you define in C# will inherit from exactly one class.

You can explicitly define a base class that the new class inherits from.

    public class Terrier : Dog

Or you can avoid specifying a base class when you define a new class.

    public class Terrier

If you don’t specify a base class, the new class will be automatically derived from System.Object.  You can see this by causing Intellisense to pop up for an instance of the class.  You see the class members of System.Object–e.g. Equals, GetHashCode, GetType, etc.