Blue Theme Orange Theme Green Theme Red Theme
 
Home | Forums | Videos | Photos | Downloads | Blogs | Interviews | Jobs | Beginners | Training
 | Consulting  
Submit an Article Submit a Blog 
 Login Close
User Id:
Password:
 
Forgot Password
Forgot Username
Why Register
 Jump to
Skip Navigation Links
TechnologyExpand Technology
WebsiteExpand Website
World Class ASP.NET Hosting – Click Here for 3 Months Free/NO Setup Fee!
 Resources  
Close
 Our Network  
Close
Search :       Advanced Search »
Home » C# Language » C# Interface Based Development

C# Interface Based Development

When trying to build maintainable, reusable, and flexible C# code, the object oriented nature of C# only gets us 50% of the way there. Programming to interfaces can provide us with the last 50%. Interfaced-based design provides loose coupling, true component-based programming, easier maintainability and it makes code reuse much more accessible because implementation is separated from the interface.

Author Rank:
Total page views :  242225
Total downloads :  1783
   Print Read/Post comments Post a comment  Similar Articles  
   Email to a friend  Bookmark  Author's other articles  
Download Files:
Interfaces.zip
 
Become a Sponsor

When trying to build maintainable, reusable, and flexible C# code, the object oriented nature of C# only gets us 50% of the way there. Programming to interfaces can provide us with the last 50%.  Interfaced-based design provides loose coupling, true component-based programming, easier maintainability and it makes code reuse much more accessible because implementation is separated from the interface.

What's an Interface?

 

An interface is a reference type object with no implementation.  You can think of it as an abstract class with all the implementation stripped out and everything that is not public removed.  Abstract classes are classes that can not be instantiated.  No properties or methods are actually coded in an interface, they are only defined.  So the interface doesn't actually do anything but only has a signature for interaction with other classes or interfaces.  A good analogy for an interface is a pencil and a pencil sharpener.  When we talk of a pencil and a pencil sharpener we generally know what they do and how they interact. We don't have to know the inner workings of a particular sharpener or pencil, only how to use them through their interface.

 

    public interface IPencil

    {

        void Write();

        bool IsSharp { get; }

    }

 

    public interface IPencilSharpener

    {

        void Sharpen(IPencil pencil);

    }

 

* While it is not enforced by the compiler, for consistency with the .NET framework it's a good idea to name interfaces starting with a capitol 'I'. 

Why Use Interfaces?

 

This make for a much easier "code world" in which to navigate.  Imagine if instead of learning how to drive a car and then being able to drive any car, we had to learn how to drive each instance of every car we get into.  It would be really inefficient if after learning how to drive the Ford Pinto we had to start all over again in order to figure out the Mustang.  A much more efficient way is to deal with the cars interface: the steering wheel, turn signals, gas pedal and brake.  This way, no matter what is implemented on the backend of the interface, we don't really care because in the end it subscribes to the basic car contract and that is how we will deal with it (through the interface).

 

Following our car analogy...  If we work for a company producing a component of a car, like an engine, it would be good if our engine could be used in multiple types of cars in "code world".  You can see that this is crucial to the success of our business if we need to sell the engine to multiple vendors and provide them with a basic manual on how to plug it in and make it work.  Our customer does not need to know anything about how we have implemented the interfaces (which is better for us and better for them - we keep our trade secrets and they don't need to hire someone with the knowledge base) so our engine is really just a "black-box". If we change the engine, we keep the contract the same (the interface) and our customers can just plug in any new upgraded engine we develop.

 

One of the problems we run into relying on classes where the interface is tightly coupled to their interface (which is the case when no interface is defined) is that if there is a change to the implementation there is a strong possibility that the interface will change slightly.  This can create cascading breaks through inheritance chains not only in our code, but also for other projects utilizing our classes.  As our projects mature and the amount of code increases, the impact of small changes becomes greater. This is where code reuse breaks down with non-interface based development.

 

To make our code more reusable, we can provide interfaces to our implementation.  This ONLY works if we are disciplined about not altering interfaces after they have been deployed (that would cause the same cascading breaks that non-interface development does).  We can always add functionality to an interface without breaking things, but if we alter the existing "hooks" into our implementation we loose one of the primary benefits of using the interface.  This is the downside of interface based development.  If interfaces are poorly designed and have to change or not easy to implement we will not receive the benefits of using them and all they achieve is to make our code more complex.  We need to think out the interfaces very carefully at design time before getting too far into the implementation because once they are implemented and made available to other resources they should not change.

 

Here's a concrete example using the pencil sharpener: The IPencil interface defined earlier could have been an abstract class declared as follows.  Imagine if we are working of version 2 of our great pencil-sharpening program and had a directive to modify the class to allow the writing of different strings through the "Write()" method.

 

public abstract class PencilBase

{

    private bool m_isSharp;

    private string m_message;

 

    public void Write()

    {

        Console.Write(m_message);

    }

 

    public bool IsSharp { get { return m_isSharp; } }

}

 

If we change the interface some of our client's code may no longer compile, right?  Can you see how the change to the "Write()" interface below is a bad idea:

 

public abstract class PencilBase

{

    private bool m_isSharp;

    //private string m_message;

 

    void Write(string message)

    {

        Console.Write(message);

    }

 

    bool IsSharp { get { return m_isSharp; } }

}

 

Any code referencing the "Write()" method will now be broken by this very simple change and won't compile. I'm sure you can see how, in the context of a very large and complex system, this code is not really maintainable and how any other code referencing it (or reusing it) is taking a big risk because the implementation is not "fixed".

 

If we see interfaces we know they are there to provide reuse of the underlying implementation and we know we should work around the interface so we don't break referencing code.  For example if we look at the code below, we know the PencilBase must adhere to the IPencil interface so we know we can't change the "Write()" implementation without breaking stuff.  Now, any developer who understands interface development can also easily maintain our code without breaking it (They could actually re-write all the implementation code as long as they adhere to the interface).  The IPencil interface gives everyone involved with the project a roadmap to what can be changed and what should stay the same. 

 

public interface IPencil

{

    void Write();

    bool IsSharp { get; }

}

 

public abstract class PencilBase : IPencil

{

    private bool m_isSharp;

    private string m_message;

 

    public void Write()

    {

        Console.Write(m_message);

    }

 

    public bool IsSharp

    {

        get { return m_isSharp; }

    }

}

 

Here is one possible way to make the change without breaking the interface by adding a "Message" property to the class.

 

public abstract class PencilBase : IPencil

{

    private bool m_isSharp;

    private string m_message;

 

    public string Message

    {

        get { return m_message; }

        set { m_message = value; }

    }

 

    public void Write()

    {

        Console.Write(m_message);

    }

 

    public bool IsSharp

    {

        get { return m_isSharp; }

    }

} 

A Contract

 

Another place interfaces really shine when we are defining how two classes should interact.  The interfaces for each class act as a contract.  This contract should be complete and concise so that anyone reading it can understand and implement the interface and write code that interacts with our interface.  Take a look at our IPencil and IPencilSharpener interfaces below.  You can see how IPencilSharpenes sharpens an IPencil.  This is the "30,000-foot view" and helps us and other developers understand the structure of the code on an abstract level instead of having to dig through thousands of lines of code to understand (or remember) how a PencilSharpener and Pencil class interact and the impacts of any changes to either.  If you are trying to understand any code, try getting a handle on the provided interfaces first and you are 90% of the way there.

 

    public interface IPencil

    {

        void Write();

        bool IsSharp { get; }

    }

 

    public interface IPencilSharpener

    {

        void Sharpen(IPencil pencil);

    }

 

The above interfaces are great, but could be improved because they are not really complete.  To have a complete interface "contract" between these two objects, we need a way for the IPencil to be notified when it has been sharpened by the IPencilSharpener so the IPencil can set it's "IsSharp" property back to "true".  Can you see a way to improve the interface to complete our contracts and still have reusable, maintainable code?

 

    public interface IPencilSharpener

    {

        void Sharpen(IPencil pencil);

    }

 

    public interface IPencil

    {

        string Message{ get; set; }

        bool IsSharp { get; }

        void Write();

        void OnSharpened();

    }

 

All we really have to do is add a way for the IPencil to be notified when it has been sharpened.  (You probably noticed that I've also added a "Message" property to make the IPencil more usable.)  Now any other developer could build pencils and/or pencil sharpeners that will interact with ours if they understand the contracts.  Here's how we'll implmement the interfaces.

 

    public class Pencil : IPencil

    {

        #region Constructors

 

        public Pencil(int countBeforeDull)

        {

            m_countBeforeDull = countBeforeDull;

            m_message = string.Empty;

            m_charsUsed = 0;

        }

 

        #endregion

 

        #region Member Variables

 

        private string m_message;

        private int m_countBeforeDull;

        private int m_charsUsed;

 

        #endregion

 

        #region IPencil Members

 

        public string Message

        {

            get { return m_message; }

            set { m_message = value; }

        }

 

        public bool IsSharp

        {

            get { return m_countBeforeDull > m_charsUsed; }

        }

 

        public void Write()

        {

            foreach (char c in m_message)

            {

                if (IsSharp)

                    Console.Write(c);

                else

                    Console.Write('#');

 

                m_charsUsed++; // used up a character

            }

 

            Console.WriteLine();

        }

 

        public void OnSharpened()

        {

            this.m_charsUsed = 0;

        }

 

        #endregion

    }

 

    public class PencilSharpener: IPencilSharpener

    {

        #region IPencilSharpener Members

 

        public void Sharpen(IPencil pencil)

        {

            pencil.OnSharpened();

        }

 

        #endregion

    }

 

And here's our executing code:

 

static void Main(string[] args)

{

    IPencil p = new Pencil(20);

    p.Message = "This pencil should not be dulled any time soon";

    p.Write();

 

    if (!p.IsSharp)

    {

        PencilSharpener sharpener = new PencilSharpener();

        sharpener.Sharpen(p);

    }

 

    p.Message = "That's better";

    p.Write();

 

} 

Overcoming a C# Language Limitation

 

Using C# we can only inherit from one class but can implement any amount of interfaces.  Because of this inheritance limitation, we have to be very careful of which class we choose to inherit from because we only get one.  This is a place where scalability is negatively impacted.  Once we have an inheritance hierarchy set up, it's difficult to change.  We can achieve the same results of inheritance through class composition and exposing the functionality of a "wrapped" object through an interface and our classes won't use up our "one shot" inheritance.

 

For example, if James Bond needed us to develop a pencil, we would have to be very careful how to build it because the requirements will be quite complex: the pencil could possibly be used an underwater breathing apparatus and as a one-shot gun.  The pencil also probably blows up if the pencil lead gets too short.  Using only inheritance, this would be very difficult without a complex inheritance heriarchy.  Using interfaces, it becomes easy. The code below demonstrates how we can indirectly "inherit" from a Pencil through composition and exposing the contained Pencil implementation through an interface.

 

    class BondPencil : IPencil

    {

        #region Constructors

 

        public BondPencil(Pencil pencil)

        {

            m_pencil = pencil;

        }

 

        #endregion

 

        #region Member Variables

 

        private Pencil m_pencil;

 

        #endregion

 

        #region IPencil Members

 

        public string Message

        {

            get { return m_pencil.Message; }

            set { m_pencil.Message = value; }

        }

 

        public bool IsSharp

        {

            get { return m_pencil.IsSharp; }

        }

 

        public void Write()

        {

            m_pencil.Write();

            if (!IsSharp) Console.WriteLine("Blows up killing the bad guy!");

 

        }

 

        public void OnSharpened()

        {

            m_pencil.OnSharpened();

        }

 

        #endregion

    }

 

Now we could also wrap an UnderwaterBeathingApparatus class and it's IUnderwaterBeathingApparatus and a OneShotGun class and its IOneShotGun interface and we effectively have worked around the single inheritance limitation of c#. Notice that we've also added the  functionality to the Write() method to blow up bad-guys (the BondPencil is not really meant for writing anyways).  Guess what?... Now we're using design patterns and you are looking at the GOF Decorator pattern.

 

class BondPencil : IPencil, IUnderwaterBreathingApparatus, IOneShotGun 

What's Implementing the Interface

 

When using the BondPencil or regular Pencil, it would be a good idea to do so through the interface.  That way we know that our code will not be broken if someone later comes along and changes the classes or if we ever need to us a different type of pencil (like maybe a mechanical pencil).  There will be times we want to know what concrete class we are dealing with so we don't blow ourselves up with a BondPencil.  There are a couple ways to do this.

 

1) The 'is' keyword returns a boolean value and is true if the object can be cast as the type.

 

if (p is BondPencil) return; // GET OUT OF HERE!

 

2) The 'as' keyword is similar to 'is' but 'as' returns a reference to the object if it can be cast or a null reference if it can not be cast.

 

if (null != p as BondPencil) return; // GET OUT OF HERE!

 

3) If we know it is a BondPencil and want to get at some of the other functionality, like the UnderWaterBreathingApparatus, we can force the cast.  However, this is not adviseable because if p can not be cast as a BondPencil this operation will throw an InvalidCastException.

 

(BondPencil) p 

Super Pencil

 

Let's make a mechanical pencil that's self-sharpening.  We just need to check that when it needs sharpening, we check that we are sharpening a mechanical pencil, right?

 

class MechanicalPencil: IPencil, IPencilSharpener

{

    #region Constructors

 

    public MechanicalPencil(int countBeforeDull)

    {

        m_countBeforeDull = countBeforeDull;

        m_message = string.Empty;

        m_charsUsed = 0;

    }

 

    #endregion

 

    #region Member Variables

 

    private string m_message;

    private int m_countBeforeDull;

    private int m_charsUsed;

 

    #endregion

 

    #region IPencil Members

 

    public string Message

    {

        get { return m_message; }

        set { m_message = value; }

    }

 

    public bool IsSharp

    {

        get { return m_countBeforeDull > m_charsUsed; }

    }

 

    public void Write()

    {

        foreach (char c in m_message)

        {

 

            if (IsSharp)

                Console.Write(c);

            else

            {

                this.Sharpen(this);

                Console.Write("\nSharpening...\n");

            }

 

            m_charsUsed++; // used up a character

        }

 

        Console.WriteLine();

    }

 

    public void OnSharpened()

    {

        this.m_charsUsed = 0;

    }

 

    #endregion

 

    #region IPencilSharpener Members

 

    public void Sharpen(IPencil pencil)

    {

        if (pencil is MechanicalPencil)

        {

            pencil.OnSharpened();

        }

    }

 

    #endregion

}

 

An even better way is to make sure our MechanicalPencil can only sharpen itself by modifying the "Sharpen()" method:

 

    public void Sharpen(IPencil pencil)

    {

        if (pencil.Equals(this))

        {

            pencil.OnSharpened();

        }

    } 

In Summary

 

As you saw in this article, interfaced based programming is a great way to ensure maintainability, reusability and flexibility in your code.  It does take a bit more discipline to carefully define interfaces early in the development cycle, but the payoffs are more than worth it.  If the interfaces are kept clear and concise they will not only help other developers understand our code but will also ensure a more stable and flexible code base.  Give interfaced-based development a try in your next project, if you follow the basic rules of keeping it simple, you won't regret it.

 

Until next time,

Happy coding


Login to add your contents and source code to this article
 About the author
 
Matthew Cochran
Looking for C# Consulting?
C# Consulting is founded in 2002 by the founders of C# Corner. Unlike a traditional consulting company, our consultants are well-known experts in .NET and many of them are MVPs, authors, and trainers. We specialize in Microsoft .NET development and utilize Agile Development and Extreme Programming practices to provide fast pace quick turnaround results. Our software development model is a mix of Agile Development, traditional SDLC, and Waterfall models.
Click here to learn more about C# Consulting.
 
Introducing MaxV - one click. infinite control. Hyper-V Hosting from MaximumASP.
Finally – a virtual platform that delivers next-generation Windows Server 2008 Hyper-V virtualization technology from a managed hosting partner you can truly depend on. Visit www.maximumasp.com/max for a FREE 30 day trial. Hurry offer ends soon. Climb aboard the MaxV platform and take advantage of High Availability, Intelligent Monitoring, Recurrent Backups, and Scalability – with no hassle or hidden fees. As a managed hosting partner focused solely on Microsoft technologies since 2000, MaximumASP is uniquely qualified to provide the superior support that our business is built on. Unparalleled expertise with Microsoft technologies lead to working directly with Microsoft as first to offer IIS 7 and SQL 2008 betas in a hosted environment; partnering in the Go Live Program for Hyper-V; and product co-launches built on WS 2008 with Hyper-V technology.
Dynamic PDF
ceTE software specializes in components for dynamic PDF generation and manipulation. The DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and new content to existing PDF documents from within your applications.
Go.NET
Build custom interactive diagrams, network, workflow editors, flowcharts, or software design tools. Includes many predefined kinds of nodes, links, and basic shapes. Supports layers, scrolling, zooming, selection, drag-and-drop, clipboard, in-place editing, tooltips, grids, printing, overview window, palette. 100% implemented in C# as a managed .NET Control. Document/View/Tool architecture with many properties&events. Optional automatic layout.
Dundas Software
Dundas Chart for .NET is the most advanced .NET charting package available today.  With an extremely complete feature set, elegant architecture and easy implementation, Dundas Chart can quickly add advanced Charting functionality to enhance and transform ASP.NET and Windows Forms applications.  Whether you are implementing charting into internal projects, or building applications for clients, Dundas Chart offers advanced technology and advanced results to get the most out of data.
Clickatell's SMS Gateway
Clickatell's Developer Solutions allow you to SMS enable any website or application via a range of API's. Learn More about our API connections.
Free access to .NET Memory Management video
Everything you need to know about Garbage Collection, Temporary Objects, Fragmentation, Finalization and common causes of memory leaks in .NET. Watch the video here.
Microsoft Visual Studio 2010 Professional
Microsoft Visual Studio 2010 Professional will launch on April 12, but you can beat the rush and secure your copy today by pre-ordering at the affordable estimated retail price of $549 (US). Pre-order now.
Nevron Chart for .NET 2010.1 Now Available
The leading .NET charting control now features PDF, Flash and Silverlight export, visualization of large datasets and more. Deliver true charting functionality to your BI, Scorecard, Presentation or Scientific apps. Download evaluation now.
Developer-Ready ASP.NET 2.0 Web Hosting with 3 MONTHS FREE
Now supporting .NET 3.0 Framework with Windows Workflow Foundation, Windows Communication Foundation (WCF), Windows Presentation Foundation (WPF), windows CardSpace (WCS)! Providing more flexibility for Developers with Web Services Support and a User/Permission Manger. Also supporting MS SQL 2005/2000 with Real-Time Backups, FREE Automated Attach .MDF Tool, FREE SQL Restore and Shrink SQL DB Tools, and SQL
 
   Print Read/Post comments Post a comment  Similar Articles  
   Email to a friend  Bookmark  Author's other articles  
Download Files:
Interfaces.zip
 
 Post a Feedback, Comment, or Question about this article
Subject:  
Comment:  
Become a Sponsor
 Comments
Good by Yogesh On April 7, 2006
Very Good article
Reply | Email | Delete | Modify | 
Re: Good by Yogesh On April 7, 2006
thanks
Reply | Email | Delete | Modify | 
Really good by jamshid On April 7, 2006

Good, Thanks for sharing

Reply | Email | Delete | Modify | 
Client/Server Contract by Sarbjit On October 16, 2006

Hey,

I know you are trying to use the concept of COM here which is inturn you wanted to explain COM. Yes, you are right we should follow this type of client/server contract using Interfaces as we use to do in COM defining Libraries and Interfaces in the IDL files. We use to put the implementation in the seperate class files and use base class pointers to point any of the derived classes.

Can you send me a sample code to proove client/server contract. I will change the implementation and compile the code, and will not compile the client and will check how it will work.

Reply | Email | Delete | Modify | 
very good by christo On May 8, 2007
goo articles
Reply | Email | Delete | Modify | 
WebControls? by jaime On July 19, 2007
Hi ! I am of Chile You have an example of WebControls ???
Reply | Email | Delete | Modify | 
WebControls? by jaime On July 19, 2007
Hi ! I am of Chile You have an example of WebControls ???
Reply | Email | Delete | Modify | 
WebControls? by jaime On July 19, 2007
Hi ! I am of Chile You have an example of WebControls ???
Reply | Email | Delete | Modify | 
good by ramanujam On September 20, 2007
How Interfaces helps in Events
Reply | Email | Delete | Modify | 
Very helpful article, but I have a question: by No On October 23, 2007
In the code block that follows, Pencil is typed as IPencil and PencilSharpener is just typed as PencilSharpener. Why is PencilSharpener not typed as IPencilSharpener. Thank you! static void Main(string[] args) { IPencil p = new Pencil(20); p.Message = "This pencil should not be dulled any time soon"; p.Write(); if (!p.IsSharp) { PencilSharpener sharpener = new PencilSharpener(); sharpener.Sharpen(p); } p.Message = "That's better"; p.Write(); }
Reply | Email | Delete | Modify | 
Thank You by Marnoch On February 10, 2008
I know this has been up for quite some time but I certainly appreciate your efforts. Interfaces have always been an enigma to me but I think I have a handle on it now. Thanks Again
Reply | Email | Delete | Modify | 
Equals ?! by Bart On December 10, 2008
Hi, Good article, but I couldn't happen to overlook the Equals you use to check 'identity' - as surely you know Equals is meant to test equality and not same identity. Of course, the default behavior is the same but the IPencil you get in Sharpen() could have been overridden and test equality by testing just, say, Message and 'IsSharp' and you'd be sharpening another pencil..... Bart de Boer
Reply | Email | Delete | Modify | 
embedded programing in c# by bharat On March 14, 2009
hello sir give me example of embedded prongraming in c#
Reply | Email | Delete | Modify | 
need for Interface by Arati On December 7, 2009
Good article. But i want to know when all the methods are public in the class which implements Interface,then why need to implement interface.This can be done without the interface,then why need interfaces?
Reply | Email | Delete | Modify | 
Overcoming a C# Language Limitation by Theo On January 2, 2010
"The code below demonstrates how we can indirectly "inherit" from a Pencil through composition"

I believe you meant to say "through aggregation".
Reply | Email | Delete | Modify | 

 Hosted by MaximumASP  |  Found a broken link?  |  Contact Us  |  Terms & conditions  |  Privacy Policy  |  Site Map  |  Suggest an Idea  |  Media Kit
Current Version: 5.2009.6.2
 © 2010  contents copyright of their authors. Rest everything copyright Mindcracker. All rights reserved.