Understanding Interfaces in .NET
by Nick Harrison06/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
|
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.
- The expression must implement the IEnumerable interface.
- The items in the collection must be convertible to the
typespecified.
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.
IComparableis used to ensure that your class is sortable.IClonableis used to ensure that your class can be cloned. Cloning simply creates another instance of the class -- a duplicate of the original.IFormattableis used to change the behavior when a user of your class invokes theToStringmethod.IDisposableis 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.
You must be logged in to the O'Reilly Network to post a talkback.
Showing messages 1 through 11 of 11.
-
Really great job Nick!
2003-07-23 10:04:55 anonymous2 [Reply | View]
I was confused about interfaces. The explanation and the examples you gave here were brillian. Now I understand what interfaces are and how to use them in my ASP.NET application.
I could rate it 11 stars out of 10 :D
Thank you very much and keep up the good work.
-
interface naming
2003-07-03 16:24:24 revdiablo [Reply | View]
Is it just me, or is the convention of prefixing interface names with I more than slightly annoying? I mean... c'mon... we can tell it's an interface by the way it's defined and used, what's up with the silly prefixes? :) -
interface naming
2003-07-04 14:51:45 anonymous2 [Reply | View]
I think it is a matter of feeling:
If you handle an object and you write code
you feel different, if you handle objects of any type IXxxxx or if you handle objects of the type Xxxx. You always know that you dont really got an
object of the type IXxxx. You only got an object, which ALSO can do the things of IXxxx. It is sometimes really different if you just have a inherited class type object or a interface TO an object. If you dont FEEL right you wont CODE right. Of course your tool can tell you, if you have an interfaced or an inherited object. But this is only implicit. The explicit way is to use IXxxxx.
For example in our company we have at the first look "silly" prefix for function/method parameters:
We just write a little "y" as prefix.
That is also a matter of "feel". You feel that you handle a parameter. If you want to code straight forward, you want to always use the same schema:
You have INPUT, do something, you have OUTPUT.
For example:
public int Add(int yA,int yB)
{
int returnValue=yA+yB;
return returnValue;
}
It is just also a "silly prefix".
But it helps you to feel the correct way.
I think there is the same way to the IXxxxx.
It just helps you to feel the correct way.
Please reply with comments!!
-
Don't have to be a genius to understand interfaces
2003-07-02 12:45:00 anonymous2 [Reply | View]
Come on ! Interfaces are quite easy to understand. Don't post an article on that so that the author can gain great credit. If you want to learn about interfaces, grab the C# in a nutshell book and read it. Once you understand the basic idea of an interface in the book, you won't have any other problem with them. -
Don't have to be a genius to understand interfaces
2003-07-02 13:33:19 anonymous2 [Reply | View]
Just because they may have been easy for you don't belittle the rest of us who struggle with such things.
This was actually the best explanation I have seen. Some of us appreciate articles such as this. -
Don't have to be a genius to understand interfaces
2003-07-03 12:37:08 anonymous2 [Reply | View]
This article mistates the history of interfaces, confuses objects and types, is incorrect on the manner in which the foreach loop works, and has a poorer explanation than is available in the free online help. Other than that, I guess it's OK.
-
New Fangled Interfaces
2003-07-02 08:03:55 anonymous2 [Reply | View]
".NET introduces the concept of an interface." - Are you drunk? Or perhaps you just meant "The new (.NET) versions of some languages, like VB.NET, now support interfaces"? -
New Fangled Interfaces
2003-07-06 16:26:18 anonymous2 [Reply | View]
Or to mention the fact that Java has had similar interfaces for nearly ten years. The idea of an interface is not new or revolutionary, and definately not introduced with .NET. -
New Fangled Interfaces
2005-01-27 09:30:56 Larutan [Reply | View]
VB had interfaces before VB.NET. It didn't have the same look as it does in .NET when creating an Interface.
(.NET lets you know its an interface)
Interface
.
.
.
End Interface
In old VB you just created a new class module (with only methods and properties). In fact that's why you were supposed to put an 'I' at the beginning of your interface name (COM standards). Otherwise it just looked like a regular class.






Anyway, cool, thanks for posting.