HomeSearch

C# Interface Examples

Share 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?Class
With interfaces, this is possible. Interfaces make programs more compact and easier to maintain. This extra complexity leads to greater simplicity.
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. } } Output Read
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.Dictionary

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 } } } Output 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.Property
C# program that uses properties, interface using System; interface IValue { int Count { get; set; } // Property interface. string Name { get; set; } // Property interface. } class Image : IValue // Implements interface. { public int Count // Property implementation. { get; set; } string _name; public string Name // Property implementation. { get { return this._name; } set { this._name = value; } } } class Article : IValue // Implements interface. { public int Count // Property implementation. { get; set; } string _name; public string Name // Property implementation. { get { return this._name; } set { this._name = value.ToUpper(); } } } class Program { static void Main() { IValue value1 = new Image(); IValue value2 = new Article(); value1.Count++; // Access int property on interface. value2.Count++; // Increment. value1.Name = "Mona Lisa"; // Use setter on interface. value2.Name = "Resignation"; // Set. Console.WriteLine(value1.Name); // Use getter on interface. Console.WriteLine(value2.Name); // Get. } } Output 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.

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); } } } Output 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.VirtualBenchmark

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: The virtual call is faster. Changing interfaces to base classes with virtual methods can speed up method invocations.

However: The performance loss with the interface method is tiny. The big picture is more important.

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(); var s1 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { interface1.Y(); } s1.Stop(); 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")); Console.Read(); } } Output 3.21 ns Interface method call 2.24 ns Virtual method call
Notes, above benchmark. Both interface method invocations and virtual method calls inject add a level of indirection. But the runtime seems to perform better with virtual methods.
Performance, notes. Avoiding interfaces may increase complexity over a project's life cycle. It may require more debugging code. This will reduce performance.

Tip: The effects of these changes are sometimes unexpected. Many considerations factor into 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.Switch
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.

IEnumerable

IList: The IList interface is a generic interface that is implemented by arrays and the List type.

IList

IDictionary: The IDictionary interface describes a lookup or dictionary collection. It has lookup methods, including TryGetValue.

IDictionary

IComparable: The IComparable interface describes how a type is sorted against other instances of the same type.

IComparable
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.

Base set. We use the mathematical concept of transitive closure. This tells us what set of interfaces form the base interfaces. This helps us figure out type hierarchies.
Base set, notes. A base set is "the explicit base interfaces and their base interfaces." An interface has the base interface of its immediate ancestor—and all further ancestors (13.1.3).

So: Interfaces in the C# language can be described, mathematically, with the concept of transitive closure.

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.
Notes, complexity. Much of the complexity in software is due to the bugs left behind by other programmers. But a program sometimes has essential complexity.

Essential complexity: Complexity in software that occurs because of the original problem's complexity.

Accidental complexity: This is complexity in software that occurs because of poor design choices.

Research. The more you read, the more you know. This is true unless you read the same book over and over again. If you do that, I probably cannot help you.

Quote: An interface defines a contract (The C# Programming Language).

Quote: Prefix interface names with the letter I, to indicate that the type is an interface (Framework Design Guidelines).

Research, Code Complete. A program's execution can be modeled on data in memory. Some techniques use type codes or enums. Object-orientation uses the type of the object.EnumObject

And: This helps the compiler check correctness. Interfaces encode behavior in data—and retain the compiler's useful checks.

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-2019 Sam Allen. Every person is special and unique. Send bug reports to info@dotnetperls.com.
Home
Dot Net Perls