An interface describes a part of the behavior of an object. If a class or struct implements that interface, then objects of that type support that behavior.
A class or struct may implement several interfaces and an interface may be implemented by many classes or structs.
The format for an interface looks like this:
public interface IName { // methods, properties, indexers, events }
Interfaces are commonly declared as public, but other access specifiers are allowed.
All the items in an interface are implicitly declared as public and abstract. If a class implements the interface, as in
public class ClassName : IName { ... }
then it must define or declare all the members of the interface.
An interface cannot contain constants, fields, operators, instance constructors, destructors, or types. Interface members are automatically public, and they cannot include any access modifiers. Members cannot be static.
An interface is typically used when unrelated classes need to share common methods, that is, with the same name. It is not unreasonable to say an interface contains (in particular) prototypes for methods.
By convention, the name of an interface starts with 'I'.
Example
One of the built-in features of arrays in C# is sorting. For instance, we could have
int [] Values = { 1, 9, 3, 7, 5 };
and then use
Array.Sort(Values);
and now the elements of Value are in ascending order.
Suppose instead we have
class Date { int Day; int Month; int Year; } Date [] OurDates;
On some later occasion, we want to sort OurDates. In order to use Array.Sort(), we need for the Date class to support an interface called IComparable
class Date : IComparable
The IComparable interface (in the System namespace) contains one prototype
int CompareTo(Object);
and the Date class must have a method
int CompareTo(Object D) { ... }
which returns 0 for "this == D", a positive value for "this > D" and a negative value for "this < D".
Now we can sort OurDates easily:
Array.Sort(OurDates);
(It is interesting to compare this to the qsort() function in the C language.)
Another interface in the Framework Class Library is IEnumerator. It is used to iterate through the the elements of a collection (such as an array), one element at a time. It has methods:
The IEnumerator interface is needed to use the "foreach" construct.
Another standard interface is IEquatable<T>. It is used by methods such as the Contains method of the List collection. It has one requirement, a method:
bool Equals(T Other) { ... }
which determines whether the current instance is equal to Other.
Interfaces are somewhat like abstract classes. There are some differences: an abstract class could contain fields, and it could contain methods that are implemented. With classes in C#, we have only single inheritance; it is possible to have multiple inheritance with interfaces.
Invented Example
Suppose we want to be able to display the data in an instance of the Date class in a MessageBox. We might want it to be formatted in some particular way, so we need a method to do all of this.
We might have other classes and want to be able to display all or some of their data in MessageBoxes.
We could have an interface:
public interface IMBox { void MBoxOut(); }
and we could then have each class implement IMBox:
class Date : IMBox
An advantage of this is that with any of these classes, we use the same method name to accomplish the same purpose.
It is possible to have properties in an interface. For example:
public interface ISampleInterface { // Property declaration: string Name { get; set; } }
A class implementing the interface would need to have a data member of type string and define the get and set accessors for it.
It is possible to have inheritance among interfaces. The format for this is:
public interface IName1 : IName2
or for that matter, we could have multiple inheritance:
public interface IName1 : IName2, IName3
Here IName2 and IName3 must be at least as accessible as the interface itself.
If the base interfaces listed are themselves derived from other interfaces, then the new interface inherits from all of these earlier base interfaces.
Example (adapted from a MSDN page):
interface IControl { void Paint(); } interface ITextBox: IControl { void SetText(string text); } interface IListBox: IControl { void SetItems(string[] items); } interface IComboBox: ITextBox, IListBox {}
The base interfaces of IComboBox are IControl, ITextBox, and IListBox.
In other words, the IComboBox interface above inherits members SetText and SetItems as well as Paint.
A class or struct that implements an interface also implicitly implements all of the interface's base interfaces.
It is possible (and not unusual) to find that a class implements several interfaces and that the interfaces have methods with similar names. Thus we might have:
public class ABC : IDEF, IGHI
where the interfaces IDEF and IGHI each have a method called DOIT. If the two needed methods called DOIT do exactly the same thing, we have no problem. If they are different, we need (in defining the class ABC) to tell them apart:
public void IDEF.DOIT(...) {..} public void IGHI.DOIT(...) {...}
Now suppose in some other code we have an instance of ABC:
public ABC MyABC;
If we use MyABC.DOIT, which version will we have? The solution for this is as follows:
IDEF TempDEF = (IDEF) MyABC; EGHI TempGHI = (IGHI) MyABC;
This looks a bit odd, as IDEF and IGHI are not classes and we do not normally think of having instances of an interface. What this does is give us TempDEF, which can be thought of as "MyABC as implementing the IDEF interface". TempDEF can be used to refer to anything defined in IDEF, so it makes sense to refer to TempDEF.DOIT, and we will have the correct version of DOIT. Do not use TempDEF for anything else.
If you want to read about this, look for "explicit interface implementation".
Interface versus class
While an interface is not a class, you will occasionally find an interface appearing as a return type. For instance:
IDataReader MyReader = MyCommand.ExecuteReader();
Here MyReader is returned by ExecuteReader(). It is a variable, so it is an instance of some class. What class is it? The short answer is that we don't know. What we do know is that whatever class is involved, it is a class that implements the IDataReader interface. The only properties and methods we can use for MrReader are those defined in IDataReader.
This may seem odd, but this is actually an example of polymorphism. What makes MyReader useful is that is satisfies the IDataReader interface, and that's all we need.