#434 – Interfaces

An interface is a list of methods, properties, events and indexers that a class may implement.  The declaration of an interface looks similar to a class declaration, but doesn’t contain an implementation for any of its members.

        public interface ICowHerd
        {
            // Properties
            string HerdName { get; set; }
            string HerdMotto { get; set; }
            List<CowInfo> Cows { get; set; }

            // Methods
            void DisplayHerdInfo();
            void DisplayCowInfo(int cowIndex);

            // Events
            event EventHandler<CowAddedEventArgs> CowAdded;
        }

You can’t do anything with an interface by itself. You can’t instantiate it like a class.  Instead, a class can choose to implement an interface, which means that it will define an implementation for every member of the interface.  You can think of the interface as a contract that dictates the exact members that a class must implement if it decides to implement the interface.

 

#433 – All structs Inherit from System.ValueType

Unlike classes, user-defined structs do not support explicit inheritance.  You can’t inherit a struct from something else.  Instead, every user-defined struct implicitly inherits from System.ValueType, which in turn inherits from System.Object (object).

You also cannot ever explicitly inherit from System.ValueType.

#432 – Initialize Multiple Objects in a using Statement

The using statement defines the scope in which an object can be used, automatically calling the object’s Dispose method when it goes out of scope.

You can declare and initialize more than one object in a using statement, as long as they are all the same type.  All of the objects will be disposed when the scope of the using statement ends.

            using (StreamWriter writer = new StreamWriter(@"D:\Remember.txt"),
                   writer2 = new StreamWriter(@"D:\Legacy.txt"),
                   writer3 = new StreamWriter(@"D:\Clothing.txt"))
            {
                writer.Write("RIP Steve Jobs, 1955-2011");
                writer2.Write("Apple II, Macintosh, iMac, iPhone, iPad");
                writer3.Write("Jeans. Turtleneck.");
            }

#431 – The using Statement Automates Invocation of the Dispose Method

A class may implement the IDisposable interface, providing a Dispose method, to allow for deterministic destruction.  Client code calls Dispose when it is done using the object, telling it to release resources that it might be holding.

It can be hard to ensure that you always call Dispose when appropriate, especially when exceptions occur.

The using statement in C# specifies the scope in which you want to use an object and guarantees that the Dispose method will be called when the object goes out of scope.

            using (StreamWriter writer =
                new StreamWriter(@"D:\Remember.txt"))
            {
                writer.Write("RIP Steve Jobs, 1955-2011");
            }

If we look at the IL generated for the using statement, we can see that it is converted to a try/finally block and the Dispose method of the StreamWriter object is called in the finally block.

#430 – A Dispose Pattern Example

If you want to control when an object’s unmanaged resources are released, you can follow the dispose pattern, implementing a Dispose method.

Here’s a complete example.  We create a method to release resources that is called either when a client invokes Dispose directly or when the CLR is finalizing the object.

    public class Dog : IDisposable
    {
        // Prevent dispose from happening more than once
        private bool disposed = false;

        // IDisposable.Dispose
        public void Dispose()
        {
            // Explicitly dispose of resources
            DoDispose(true);

            // Tell GC not to finalize us--we've already done it manually
            GC.SuppressFinalize(this);
        }

        // Function called via Dispose method or via Finalizer
        protected virtual void DoDispose(bool explicitDispose)
        {
            if (!disposed)
            {
                // Free some resources only when invoking via Dispose
                if (explicitDispose)
                    FreeManagedResources();   // Define this method

                // Free unmanaged resources here--whether via Dispose
                //   or via finalizer
                FreeUnmanagedResources();

                disposed = true;
            }
        }

        // Finalizer
        ~Dog()
        {
            DoDispose(false);
        }
    }

#429 – Use the Dispose Pattern for Deterministic Destruction

You can implement a finalizer in a class to explicitly release unmanaged resources before an object’s memory is freed.  Drawbacks of this approach include:

  • You don’t control when the object’s resources are cleaned up
  • A finalizer can’t make use of any other managed objects  (they may have already been finalized)

Another pattern for releasing unmanaged resources is for a class to implement the IDisposable interface by providing a Dispose method.  Dispose is meant to clean up the object’s resources when it’s called.  A client of the class can decide exactly when it wants to release the object’s resources (deterministic destruction).  Benefits of this pattern include:

  • Can release resources earlier, not waiting for finalization
  • Dispose logic can make use of other managed resources
    public class Dog : IDisposable
    {
        public void Dispose()
        {
            // Release unmanaged resources here

            // Note: need logic to prevent double disposal, etc.
        }

#428 – A Finalizer Should Always Call the Finalizer of Its Base Class

An implementation of Object.Finalize for a particular class in .NET should always call the Finalize method of its base class.  In the case of C#, you can’t explicitly override Finalize, but you provide a finalizer using the destructor (~) syntax.  When you do this, the compiler will automatically add code to ensure that your destructor calls Finalize in the base class.

In the example below, I write a simple destructor for the Dog class.  We can see in the IL that the Finalize method has been overridden and that it calls System.Object.Finalize in the finally clause.

        ~Dog()
        {
            Trace.WriteLine("This dog is on the way out..");
        }

#427 – Finalizer Gotchas

The idea of the finalizer in .NET is that you can override the Object.Finalize method, called by the garbage collector when it’s releasing memory for an object, and you can do any required cleanup of unmanaged resources.

There are several things to keep in mind if you want to write a finalizer (done in C# using the destructor syntax):

  • You can’t predict when your finalizer is called
  • The finalizer might never get called at all
  • The order that finalizers are called in is unpredictable.  You therefore can’t assume that any other managed object that your object references still exists, or is in a known state.
  • Garbage collection will take longer if you have objects with finalizers

 

#426 – Use a Destructor to Free Unmanaged Resources

When an object is no longer referenced by other objects, its memory may be reclaimed by the garbage collector in the CLR.  If you have any unmanaged resources that you need to clean up explicitly, you can implement a finalizer for your class.

A finalizer is the implementation of the Object.Finalize method for your class, which the garbage collector calls when it’s ready to release memory for an object.  In C#, you implement a finalizer using the destructor syntax–a method defined as a tilde (~), followed by the name of the class.

    public class Dog
    {
        ~Dog()
        {
            Trace.WriteLine("This dog is on the way out..");
        }

When you look at the IL for this class, you’ll see that the compiler has overridden the Finalize method.

You’ll notice that this method is now called when the garbage collector is releasing the object.

#425 – Nondeterministic Destruction and Object Finalization

In .NET, the CLR (Common Language Runtime) is responsible for reclaiming memory for objects that are no longer being referenced, through garbage collection.

Garbage collection can be done on an object as soon as it’s no longer being referenced by any other objects.  However, the garbage collector may not free memory for an object immediately.  It can choose to free up memory for an object whenever it likes.

Every object has a Finalize method that you can override, which will be called when the object is being destroyed.  This method allows cleaning up any unmanaged resources the object might hold, before the object is destroyed.

The CLR implements nondeterministic destruction–you can’t explicitly force an object’s Finalize method to be called and you can’t predict when it is called.  There’s also no guarantee that the finalizer will ever be called–an application might crash before the finalizer is called.