C# Interface

Array Class Collections File Keyword String .NET ASP.NET Cast Compression Data Delegate Directive Enum Exception If Interface LINQ Loop Method Number Process Property Regex Sort StringBuilder Struct Switch Time Windows WPF

Interface

A program has classes,
methods
and properties. What if these members could be used in a unified way? Less code would be needed. With interfaces this is possible. Interfaces make programs more compact and easier to maintain.

Example

This program defines an interface named IPerl, which requires one void Read method. It defines a class named Test. The Test class implements IPerl. This means it must implement the Read method.

Then:In the Main method, we create a Test instance and store it in an IPerl reference. We invoke the Read method from the interface.

Interface example: IPerl

Tip:When a class implements an interface, it can be used through a reference to that interface.

Based on:

.NET 4.5

Program that uses interface: C#

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

Example 2

Collections: circles in square

Next, we see how interfaces can be used in collections. This program defines an interface and two 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 based on the value.

Program that uses interface implementations: C#

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());

	// Lookup 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
Method call

In this example, we define an interface named IValue with a single method. All types that implement this interface must then have a member with the identifier Render. The signature must also be the same.

Note:When the Render method is invoked on an interface reference, a different one is chosen depending on the program's internal.

Class shapes

Next, the program shows two implementations of IValue. These are for Content and Image objects. Each of these classes uses the colon syntax to specify the IValue interface. It then provides the required Render method.

In Main, a new Dictionary is created. It is populated with three key-value pairs. The key is a string and the value is either Content or Image. These are classes that implement IValue.

Dictionary

Note:You cannot create a new IValue(). Instead you must create instances of objects that implement that interface.

Finally, TryGetValue is called. The program takes string literals and then executes the object's method based on its type. You do not need to specify the type of the implementation. The type is known by the runtime.

TryGetValue

Names

Interface types are usually named with a first letter of I. There is no language-based constraint on this. Instead, this is a convention.
As usual with a convention,
some experts love it
and others hate it.

Tip:You can read more about interface naming conventions in the book .NET Framework Design Guidelines.

Framework Design Guidelines

Caution:The name "IPerl" is a poor example of an interface name, despite its leading letter. It indicates no functionality.

Behavior

Note

In Code Complete, we learn how a program's execution can be modeled on data in memory. Some techniques use type codes or enumerations. Object-orientation uses the type of the object. This helps the compiler check correctness.

Code Complete

And:In this way, the interface implementation here encodes behavior in the data while retaining the compiler's useful checks.

Complexity

Collection abstraction: squares

Much of the complexity in software is due to non-essential difficulties such as the bugs left behind by other programmers. But a program sometimes has essential complexity. In this example, the object-orientation is essential.

In the program, the selection of what method to invoke must always be made. The example does not promote accidental complexity. The interface type does not make the program needlessly complex.

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.

Property

Property

We next see how can you can specify properties on an interface. The syntax for a property type on an interface declaration is different. The interface declarations do not include modifiers such as "public."

But:The classes that implement the properties must include those modifiers. This makes the interfaces easier to read.

Tip:Recall that interface accesses may perform a virtual method dispatch. This means the method calls are somewhat more expensive.

PropertyIndexer
Program that uses properties, interface: C#

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
Squares

The program contains one interface type definition. IValue is a contract. It requires implementations to have two properties. A Count property and a Name property must be present.

Note:The properties in the interface itself simply use empty get and set statements.

Also, the program includes two classes that implement the IValue interface in different ways. The classes contain properties, as you see in any class. No special syntax here is needed.

The Name property uses an explicit backing store field. And the Count property is automatically implemented. The Main method then accesses the property implementations through the interface type.

Main MethodProgramming tip

Tip:Interfaces that stipulate properties can use empty get and set statements in curly parenthesis in the interface definition.

And:You can implement the interface in classes and use regular properties with the same names there.

Built-in

Framework: NET, Visual Studio screenshots

In your programs, most of the interfaces you use will be built into the .NET Framework itself. The Framework is implemented with extensive interface use. We show some core ones in the .NET Framework.

IEnumerable:The IEnumerable interface is used with many collections and also with LINQ.

IEnumerableIEnumerable, Array

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

Base set

Base keyword

We use the mathematical concept of transitive closure. This tells us what set of interfaces form the base interfaces. And this helps us figure out type hierarchies in object-oriented languages.

The base set includes "the explicit base interfaces and their base interfaces." An interface has the base interface of its immediate ancestor. It also has all of its further ancestors in the hierarchy (section 13.1.3).

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

Performance

Virtual keyword

In many benchmarks, using a simple switch statement performs slightly better than using virtual methods. But with later changes the switch statement may grow in size and reduce speed.

Also, avoiding object-oriented design may increase complexity over a project's lifecycle. It may require more debugging code. This will reduce performance. The effects of these changes are sometimes unexpected.

SealedQuestion

Suppose you have the option of using interfaces or virtual methods. Which version is faster? We benchmark interfaces against virtual methods. We provide data about which is faster.

Interface Performance

Tip:The absolute performance loss with the interface method is tiny, often less than a nanosecond.

So:First make sure the big picture of objects in your program is correct. Then think about optimizations.

Summary

Interfaces are used with classes. During execution, the runtime selects an interface implementation. No exact type is specified in the source code. In this way, we use the type system itself to encode behavior as data.

C#