Are interfaces evil or misused?

There are several considerations and practices concerning interfaces

Some developers say that interfaces can be used as a replacement of multiple inheritance mechanisms, which cause complexity and ambiguity. But each feature must be implemented each time it is declared: this is not an inheritance, this is a wrapper to the description of a part of a group of classes, like IDisposable. It is the same as a multiple inheritance with one implemented class and some abstract classes: it is a particular case which allows only one way hierarchy with interfaces as abstract connectors that describes services.

Some developers say that interfaces can be used to separate the access to an object of this instance. Historically, interfaces are a COM & DCOM heritage: they are used to manipulate components services, whatever objects are, where they are, and how they are implemented. Interfaces are not a replacement to multiple inheritance, they are something else.

Recommended articles:
A plea for full multiple inheritance support in .NET
A Typed Intermediate Language for Compiling Multiple Inheritance

Interfaces can be used to solve some design issues in .NET

In component communication, because they are like a transfer of addresses: “An interface describes a group of related functionalities that can belong to any class or structure. Interfaces can consist of methods, properties, events, indexers, or any combination of those four member types. An interface cannot contain fields. Interfaces members are automatically public” (MSDN Documentation). To simplify, in distributed computing, a client has an “instance” of an interface to an object that is on the server.

In the conceptualization of services provided by classes instead of multiple inheritance: this abstraction layer should be separated from the classes layer. It is not an implementation because it is a high-level design view and this should not be coded: a method should not be implemented several times in the same way, which is facilitated by the genericity. An interface corresponds to a fully implemented class, to a class that contains abstract members, or to a fully/pure abstract class.

To provide a kind of low level polymorphism for generic classes to manipulate all possible linked templates while this feature doesn’t exist in C#: an undetermined type like GenericClass < > can’t be used without providing a specific type unless reflexion is used.

But they create some problems

All functionalities must be implemented each time.
The type dependence is fragmented to the detriment of quality.
The code complexity is increased: lots of declarations and big code for one class instead of lots of small classes with small code.

Using interfaces in implementation increases the abstraction of an abstraction, reduces the code factorization, reduces the maintainability and increases the risks of a project.

Multiple inheritance may be used to solve some design problems in .NET

To inherit from multiple classes and to implement only once a service provided by several classes.
To have a strongly typed design without seeing double or going crazy.
To provide a high level of polymorphism.

But it creates some problems

All functionalities must be implemented rigorously.
It requires a study and an understanding of the object programming theory.
The code complexity is increased: lots of small classes with small code instead of lots of declarations and big code for one class.

Using multiple inheritance increases the simplicity of the abstraction (of interfaces, if models are based on), reduces the code size, reduces the confusion about models and increases the safeness of a project.

Interfaces don’t compensate for the lack in multiple inheritance as well as in generic polymorphism

Both have their difficulties, their advantages and their applications : discuss the pros and cons of interfaces is a wrong debate without end.

Code based on interfaces is a default programming and an entangled path based on a difficult simplification of what objects and components are. Interfaces are a full or a partial copy of a class description: they don’t provide better software experience but better ways to design. The mechanisms of interfacing in distributed environment should be provided by the CLR and based on classes descriptions which are the interfaces : the virtual tables.

Of course, do not use interface and multiple inheritance reduces the code complexity, and a developer should have the choice depending of the work.

Consider this code:

public delegate void ConfigureEvent(IConfigurable value);

public interface IConfigurable
{
ConfigureEvent DoConfiguration { get; set; }

void Configure();
}

public class ClassA
{
}

public class ClassB : IConfigurable
{
ConfigureEvent IConfigurable.DoConfiguration { get; set; }

void IConfigurable.Configure()
{
if ( ( (IConfigurable)this ).DoConfiguration != null )
( (IConfigurable)this ).DoConfiguration(this);
}
}

public class ClassA1 : ClassA
{
}

public class ClassA2 : ClassA, IConfigurable
{
ConfigureEvent IConfigurable.DoConfiguration { get; set; }

void IConfigurable.Configure()
{
if ( ( (IConfigurable)this ).DoConfiguration != null )
( (IConfigurable)this ).DoConfiguration(this);
}
}

public class ClassA3 : ClassA1, IConfigurable
{
ConfigureEvent IConfigurable.DoConfiguration { get; set; }

void IConfigurable.Configure()
{
if ( ( (IConfigurable)this ).DoConfiguration != null )
( (IConfigurable)this ).DoConfiguration(this);
}
}

The equivalent of these 45 lines in multiple inheritance is simpler and more intuitive. It takes 30 lines: the method is implemented only once, there is no interface because classes structure are the interface, and code is better:

public delegate void ConfigureEvent(IConfigurable value);

public class Configurable
{
public ConfigureEvent DoConfiguration { get; set; }

virtual public void Configure()
{
if ( DoConfiguration != null ) DoConfiguration(this);
}
}

public class ClassA
{
}

public class ClassB : Configurable
{
}

public class ClassA1 : ClassA
{
}

public class ClassA2 : ClassA, Configurable
{
}

public class ClassA3 : ClassA1, Configurable
{
}

Supporting generic polymorphism and multiple inheritance in .NET and C# could allow making programs more stable and efficient, as well as coding like this :

public class Class1 
{
public int Class1Value { get; set; }
}

public class Class2
{
public int Class2Value { get; set; }
}

public class Class3 : Class1
{
public int Class3Value { get; set; }
}

public class Class4<T> : Class3, Class2
{
public int Class4Value { get; set; }
public T Value { get; set; }
}

public class Class5<T> : Class4<T>
{
public int Class5Value { get; set; }
public void DoSomething() { }
}

void TestPolymorphism()
{
var list = new List<class3>();

list.Add(new Class3());
list.Add(new Class4<int>());
list.Add(new Class5<int>());
list.Add(new Class5<string>());

foreach (var o in list)
{
o.Class1Value = 0;
o.Class3Value = 0;

if (o is Class2) (o as Class2).Class2Value = 0;
if (o is Class4<int>) ) (o as Class4<int>).Value = 0;

// Generic polymorphism and diamond operator is not currently available in csharp
if (o is Class5<>) (o as Class5<>).DoSomething();
}
}

It is impossible to write the last line and the problem is solved by using interfaces:

public interface IClass1 
{
int Class1Value { get; set; }
}

public interface IClass2
{
int Class2Value { get; set; }
}

public class Class1 : IClass1
{
public int Class1Value { get; set; }
}

public class Class2 : IClass2
{
public int Class2Value { get; set; }
}

public class Class3 : Class1
{
public int Class3Value { get; set; }
}

public class Class4<T> : Class3, IClass2
{
public int Class2Value { get; set; }
public int Class4Value { get; set; }
public T Value { get; set; }
}

interface IClass5
{
int Class5Value { get; set; }
void DoSomething();
}

public class Class5<T> : Class4<T>, IClass5
{
public int Class5Value { get; set; }
public void DoSomething() { }
}

void TestPolymorphism()
{
var list = new List();

list.Add(new Class3());
list.Add(new Class4<int>());
list.Add(new Class5<int>());
list.Add(new Class5<string>());

foreach (var o in list)
{
o.Class1Value = 0;
o.Class3Value = 0;

if (o is IClass2) (o as IClass2).Class2Value = 0;
if (o is Class4<int>) ) (o as Class4<int>).Value = 0;

if (o is IClass5) (o as IClass5).DoSomething();
}
}

But it is less elegant.