WindowsDevCenter.com
oreilly.comSafari Books Online.Conferences.

advertisement


AddThis Social Bookmark Button

Understanding Interfaces in .NET

by Nick Harrison
06/30/2003

.NET introduces the concept of an interface. The interface concept is potentially confusing. An interface is a contract that defines the signature of some piece of functionality. Throughout the .NET framework, interfaces are used to define that certain types have well-known behaviors. For example, the ICloneable interface specifies that a .NET type can be cloned and defines a specific programming signature for how cloning is performed. In this way, an interface both advertises a specific functionality or behavior for a .NET type and also defines the method/property signature for the behavior.

In .NET, an object can be derived from a single ancestor, yet implement any number of interfaces. There is no problem with multiple interfaces defining a common method; the object being defined would only implement the common method once. This is the difference between interfaces and inheritance. When a class is derived from another class, it automatically inherits all of the methods and properties of the ancestor. The work for the derived class is to override any methods that will be different and extend the functionality as needed. When a class implements an interface, the compiler is flagged about what methods, properties, etc. the class being defined must include, and ensures that you do so.

In this article, we will review some places where interfaces are used in .NET, talk about why you would want to define your own interface, and step through an example of defining and implementing your very own interface.

Applications You Never Thought Of

As you learn .NET, you will see interfaces used in many places. In an earlier article, I showed how interfaces are pivotal in building a database access layer independent of the actual database type. As another example, we are all also familiar with the foreach loop:

foreach (type identifier in expression) statement

Related Reading

.NET Framework Essentials
By Thuan L. Thai, Hoang Lam

This simple looping structure is based on interfaces. There are two requirements in using a foreach loop to which most of us never give a second thought.

  1. The expression must implement the IEnumerable interface.
  2. The items in the collection must be convertible to the type specified.

If you have done any work with data-bound controls, you are no doubt familiar with the DataSource property. If you look at the help for this property, you will see that it expects a value that implements the IEnumerable interface as well.

This means that any class that you create can be used as a DataSource or iterated through using the foreach loop, just like the standard built-in classes, by simply implementing the IEnumerable interface. There are several other interfaces woven into the .NET framework that simplify embedding your custom classes into the .NET framework.

  • IComparable is used to ensure that your class is sortable.
  • IClonable is used to ensure that your class can be cloned. Cloning simply creates another instance of the class -- a duplicate of the original.
  • IFormattable is used to change the behavior when a user of your class invokes the ToString method.
  • IDisposable is used to provide functionality to release any unmanaged resources, such as COM objects, that your class may be using.

Properly using these interfaces will make classes that you write integrate more tightly with the .NET framework, which will make them behave more predictably when someone tries to use them. Not only can you implement these and other predefined interfaces, you can also define custom interfaces to use in your design.

Interfaces of Your Own Design

Before diving into the details of how to define an interface, let's explore why you would want to. One reason might be to further separate the UI from the business logic, or to better define what the UI is doing. For example, imagine an interface called IMemberProfile that simply defines properties for all of the relevant fields in a member profile. Now, a web page that allows your users to view or edit their profile would not only inherit from System.Web.UI.Page, but it may also implement your custom IMemberProfile interface. Not only could a web page implement this interface, but so could a MobilePage, a Windows Form, a UserControl, a CustomControl, etc. Any method that you write expecting an IMemberProfile won't care about the base class used. The only thing that it cares about is that the class fulfills all of the requirements for implementing the interface. These methods won't care whether the property references a local variable, a drop-down menu, a text box, a database, or an XML stream. The only thing that matters is that the required properties are implemented.

If all of your business logic was implemented with methods expecting such custom interfaces, then not only would it be easy to target multiple UIs, but each UI would be protected from changes to the data requirements. If a new data value is ever required in any function call, then in the worst case, a new property would be added to the interface definition and each UI would have to implement that new property. Individual function calls would not have to change, since they are always simply passing "this," or "me" in VB.

Defining the ImemberProfile Interface

Defining an interface is a lot like defining a class, except that you don't have to get involved in the details about how anything will work. It is a lot like the header files in C/C++. For example:

public interface IMemberProfile
{
  string FirstName {get;set;}
  string LastName {get;set;}
  string Email {get;set;}
  System.Guid MemberID {get;set;}
}

This example defines an interface that will require that any class implementing it must provide read/write properties for FirstName, LastName, Email, and MemberID.

Implementing the IMemberProfile Interface

To implement an interface, you start by marking that the class you are defining will implement the interface. In C#, this is similar to the syntax for inheritance.

public class MemberProfile: System.Web.UI.Page, IMemberProfile

In VB.NET, the syntax is slightly different.

Public Class MemberProfile
  Inherits System.Web.UI.Page
  Implements IMemberProfile

The compiler will handle warning you about anything that the interface requires that is not included in your class. For this example, you simply need to include properties for FirstName, LastName, Email, and MemberID.

public string FirstName
{
 get{return txtFirstName.Text ;}
 set {txtFirstName.Text = value;}
}

public string LastName
{
 get{return txtLastName.Text ;}
 set {txtLastName.Text = value;}
}

public string Email
{
 get{return txtEmail.Text ;}
 set {txtEmail.Text = value;}
}

public System.Guid MemberID
{
  get
  {
    if (m_uniqueID.CompareTo (null) == 0)
    {
       m_uniqueID = System.Guid.NewGuid();
    }
    return m_uniqueID;
  }
  set 
  {
    m_uniqueID = value;
  }
}

Implementing an interface really requires nothing more than the rules of encapsulation would recommend.

Using Your Interface

Now that we have the interface defined and a UI that implements the interface, we are ready to write some business logic that will use this interface. Here we define two methods that will be used to retrieve the data to populate the UI, as well as a method to retrieve the data currently populated in the UI. In a real-world example, these methods would use a database to store the details. To keep this example simple, we will simply use local variables. To truly appreciate what is happening in this example, I recommend stepping through the code with the debugger and watching the properties being accessed.

The method to retrieve the current member profile details would be similar to this:

public static void RetrieveMemberProfile (IMemberProfile Profile)
{
 Profile.FirstName = "John";
 Profile.LastName = "Doe";
 Profile.Email = "jdoe@email.com";
 Profile.MemberID = 
    new System.Guid  
    ("{65C38236-CA96-4FF1-9142-00873B8BD333}");
}

The method to update the member profile details would be similar to this:

public static void UpdateMemberProfile (IMemberProfile Profile)
{
  string _FirstName;
  string _LastName;
  string _Email;
  string _MemberID;
  
  _FirstName = Profile.FirstName;
  _LastName = Profile.LastName;
  _Email = Profile.Email;
  _MemberID = Profile.MemberID.ToString();
}

In the Page_Load event, we will call the RetrieveMemberProfile method like this:

private void Page_Load(object sender, System.EventArgs e)
{
   // Put user code to initialize the page here
   if (!Page.IsPostBack)
   {
      BusinessRules.RetrieveMemberProfile (this);
   }
}

The click event handler for the button will look similar to this:

private void btnUpdate_Click(object sender, System.EventArgs e)
{
  BusinessRules.UpdateMemberProfile (this);
}

Conclusion

From this simple example, we have seen the advantages of using the built-in interfaces. We have also seen how easy it is to define and implement a custom interface, as well as a practical example of doing so and how this process can lead to a stronger separation between the UI and the business logic.

Nick Harrison UNIX-programmer-turned-.NET-advocate currently working in Charlotte, North Carolina using .NET to solve interesting problems in the mortgage industry.


Return to ONDotnet.com.