A C# program has classes, methods and properties. It would be useful if these members could be used in a unified way—we could share the required code.
With interfaces, we can reuse code. This merging of code makes programs more compact and easier to maintain (which is a big advantage).
We see an interface
named IPerl
, which requires a Read method. It defines a class
named Test. The Test class
implements IPerl
—it must implement the Read method.
IPerl
reference. We invoke the Read method from the interface
.class
implements an interface
, it can be used through a reference to that interface
.using System; interface IPerl { void Read(); } class Test : IPerl { public void Read() { Console.WriteLine("Read"); } } class Program { static void Main() { IPerl perl = new Test(); // Create instance. perl.Read(); // Call method on interface. } }Read
class
to interface
We can use the as
-keyword to convert a class
instance to an interface
type it implements. Then we check for null
to ensure the cast succeeds.
using System; interface ITest { void Message(); } class Test : ITest { public void Message() { Console.WriteLine("MESSAGE"); } } class Program { static void Main() { // Create Test object. Test test = new Test(); test.Message(); // Convert the class to its interface. ITest perl = test as ITest; if (perl != null) { perl.Message(); } } }MESSAGE MESSAGE
This program defines an interface
and 2 classes that implement it. In Main
, we create a Dictionary
. We fill it with values based on the IValue
interface
.
string
keys to look up values in the collection. The execution engine invokes the type-based implementation.if
-statements or switch
-statements are required to select the best method implementation.using System; using System.Collections.Generic; interface IValue { void Render(); } class Content : IValue { public void Render() { Console.WriteLine("Render content"); } } class Image : IValue { public void Render() { Console.WriteLine("Render image"); } } class Program { static void Main() { // Add three objects that implement the interface. var dictionary = new Dictionary<string, IValue>(); dictionary.Add("cat1.png", new Image()); dictionary.Add("image1.png", new Image()); dictionary.Add("home.html", new Content()); // Look up interface objects and call implementations. IValue value; if (dictionary.TryGetValue("cat1.png", out value)) { value.Render(); // Image.Render } if (dictionary.TryGetValue("home.html", out value)) { value.Render(); // Content.Render } } }Render image Render content
Here we see an interface
that includes a property. The interface
declarations do not include modifiers such as "public." We can use automatic property syntax.
IValue
interface
.IValue
interface
, which are implemented by Image and Article.using System; interface IValue { int Count { get; set; } string Name { get; set; } } class Image : IValue { public int Count { get; set; } string _name; public string Name { get { return this._name; } set { this._name = value; } } } class Article : IValue { public int Count { get; set; } string _name; public string Name { get { return this._name; } set { this._name = value.ToUpper(); } } } class Program { static void Main() { // Part 1: create class instances, and use interface variables. IValue value1 = new Image(); IValue value2 = new Article(); // Part 2: access properties on interfaces. value1.Count++; value2.Count++; value1.Name = "Mona Lisa"; value2.Name = "Resignation"; Console.WriteLine(value1.Name); Console.WriteLine(value2.Name); } }Mona Lisa RESIGNATION
IEnumerable
This built-in interface
is especially important. We can treat all arrays and Lists (and other collections) as IEnumerable
types—the .NET Framework is designed this way.
List
types. The element type (int
) is fixed.using System; using System.Collections.Generic; class Program { static void Main() { int[] values = { 1, 2, 3 }; List<int> values2 = new List<int>() { 1, 2, 3 }; // Pass to a method that receives IEnumerable. Display(values); Display(values2); } static void Display(IEnumerable<int> values) { foreach (int value in values) { Console.WriteLine(value); } } }1 2 3 1 2 3
interface
and virtual
Suppose you have the option to use interfaces or virtual
methods. Which version is faster? I benchmark interfaces against virtual
methods.
interface
. It calls a method through an interface
.class
virtual
method. It uses a virtual
method.interface
call appears to be faster, but both are well-optimized.using System; using System.Diagnostics; interface IInterfaceExample { void Y(); } class ImplementsInterface : IInterfaceExample { public void Y() { } } class BaseExample { public virtual void Y() { } } class DerivesBase : BaseExample { public override void Y() { } } class Program { const int _max = 100000000; static void Main() { IInterfaceExample interface1 = new ImplementsInterface(); BaseExample base1 = new DerivesBase(); interface1.Y(); base1.Y(); // Version 1: call interface method. var s1 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { interface1.Y(); } s1.Stop(); // Version 2: call virtual method. var s2 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { base1.Y(); } s2.Stop(); Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000 * 1000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000 * 1000) / _max).ToString("0.00 ns")); } }0.29 ns Interface method call 0.55 ns Virtual method call
In our programs, most of the interfaces used will be built into the .NET Framework itself. The Framework is implemented with extensive interface
use.
interface
Visual Studio will help us implement an interface
on a class
. Hover over the interface
name after specifying it.
NotImplementedExceptions
and write the C# method bodies.Interface types are usually named with a first letter I. There is no language-based constraint on this. Instead, this is a convention.
An interface
is less concrete, more abstract
. During execution, the runtime selects an implementation. With a language feature (the type system) we encode behavior as data.