#951 – Not Every Type Derives from object

C# is normally said to have a Unified Type System, that is–every type derives from object (System.Object), directly or indirectly.

This is mostly true, but not completely accurate.

Most types do derive from object, including: classes, value types, and delegates.  And all object instances that you work with will be instances of types that do derive from object.  (Or they will have a null value).

But there are several types that do not derive from object, including:

  • interface – an interface is a type that does not derive from object.  Rather, an interface can be implemented by some type that does derive from object.
  • dynamic – dynamic is a type in that you can declare variables to be of type dynamic, but it is not an actual type in the CLR that derives from object (although its semantics are similar to the semantics of object)
  • System.TypedReference – does not derive from object

#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;

            Console.WriteLine(d.ToString());
            Console.WriteLine(i.ToString());
            Console.WriteLine(awake.ToString());

950-001

#923 – An Object Isn’t Necessarily Deleted as Soon as It’s Dereferenced

An object will typically be deleted, and its memory reclaimed, at some point after the object is no longer being referenced by any reference-typed variables.

The object won’t necessarily be deleted when you stop referencing it.  The garbage collector will only delete the object when it needs to reclaim some space in memory.  We refer to this as nondeterministic destruction–the idea that we can’t predict when an object will be destroyed.

            // myDog references a Dog object
            Dog myDog = new Dog("Kirby");

            // Set reference to null, so that we
            // no longer reference "Kirby" Dog object.
            myDog = null;

            // "Kirby" won't necessarily have been
            // destroyed at this point

#922 – Ways in Which References to an Object Are Released

An object will potentially be deleted after there are no longer any references to the object.  You reference an object using a reference-typed variable.

There are several different ways in which a reference to an object can be released.

  • Change the reference-typed variable so that it refers to a different object
  • Change the reference-typed variable so that it refers to null
  • Let the reference-typed variable go out of scope (return control from the method in which the variable was declared)
        static void SomeMethod()
        {
            // myDog references the Kirby Dog object
            Dog myDog = new Dog("Kirby");

            // Refer to new Dog object,
            // no longer refer to Kirby Dog object
            myDog = new Dog("Jack");

            // Set reference to null,
            // no longer refer to Jack Dog object
            myDog = null;

            myDog = new Dog("Ruby");

            // When we leave the method, myDog
            // will go out of scope and no longer
            // refer to Ruby Dog object
            return;
        }

#921 – Objects Are Explicitly Created but Automatically Destroyed

You create an object, or an instance of a classusing the new keyword.  When you create the object, you must also refer to it using a reference-typed variable.

            // Create an instance of a Dog and reference it using
            // the "myDog" variable.
            Dog myDog = new Dog("Kirby", 15);

Using the new keyword, you explicitly create objects.

A;though you create objects explicitly, you never explicitly delete them.  Instead, an object can be deleted after it is no longer being referenced by any reference-typed variables.  Once the object has been deleted, the CLR (Common Language Runtime) will reclaim the memory that was being used by the object.

Not only do you not explicitly delete objects, you also can’t predict when the object will be deleted.  The CLR will decide when to delete the object, based on when it needs the memory that the object is using.

#826 – Deep Copies

When making a copy of an object, you can either make a shallow copy or a deep copy.  As opposed to a shallow copy, a deep copy is one in which a copy is made not only of the top-level object, but of all the objects referenced by the original object.

During the copy process, whenever a reference to a child object is encountered, a new instance (or deep copy) of the child object is made.

For example, if a Dog object contains a reference to a DogCollar object and we make a deep copy, we get the following:

826-001

When doing a deep copy, a deep copy is typically made of all child objects in the object hierarchy.  For example, if the DogCollar instance had in turn referred to another object, a copy would have been made of that object.

#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