C# Interface ExamplesShare code by using interface types. Learn about interfaces in depth.
Interface. A program has classes, methods and properties. What if these members could be used in a unified way? What if we could share this code?
Notes, interfaces. With interfaces we can share approaches to calling code. Often interfaces make programs more compact and easier to maintain.
Initial example. 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.
Main We create a Test instance and store it in an IPerl reference. We invoke the Read method from the interface.
Tip When a class implements an interface, it can be used through a reference to that interface.
C# program that uses 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. } }
Convert 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.
C# program that converts class to interface
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(); } } }
Collections. 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.
Then We use string keys to look up values in the collection. The execution engine invokes the type-based implementation.
Important No if-statements or switch-statements are required to select the best method implementation.
C# program that uses interface implementations
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
Property. 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.
Part 1 We create instances of the Image and Article classes, and reference them through the IValue interface.
Part 2 We access the properties from the IValue interface, which are implemented by Image and Article.
C# program that uses properties, interface
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); } }
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.
So We can use one method here (Display) to handle arguments of both array and List types. The element type (int) is fixed.
C# program that uses IEnumerable
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
Benchmark, interface and virtual. Suppose you have the option to use interfaces or virtual methods. Which version is faster? I benchmark interfaces against virtual methods.
Version 1 The code declares a type that implements a method from an interface. It calls a method through an interface.
Version 2 The program declares a type that implements a method matching a base class virtual method. It uses a virtual method.
Result In .NET 5 for Linux, the interface call appears to be faster, but both are well-optimized.
C# program that tests performance
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
Performance, notes. Avoiding interfaces may increase complexity over a project's life cycle. It may require more debugging code—this will reduce performance.
Performance, switch. A simple switch statement often performs slightly better than a virtual method. But with later changes, the switch statement may grow in size and reduce speed.
Built-in. In our programs, most of the interfaces used will be built into the .NET Framework itself. The Framework is implemented with extensive interface use.
IEnumerable The IEnumerable interface allows foreach-loops on collections. It is often used in LINQ.
IList The IList interface is a generic interface that is implemented by arrays and the List type.
IDictionary The IDictionary interface describes a lookup or dictionary collection. It has lookup methods, including TryGetValue.
IComparable The IComparable interface describes how a type is sorted against other instances of the same type.
Implement interface. Visual Studio will help us implement an interface on a class. Hover over the interface name after specifying it.
Then From the drop-down menu, select "Implement interface." Then remove the NotImplementedExceptions and write the C# method bodies.
Notes, names. Interface types are usually named with a first letter I. There is no language-based constraint on this. Instead, this is a convention.
A review. 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.
© 2007-2021 sam allen. see site info on the changelog