In a great many cases, people follow the "design to interfaces" principle by doing the following:
interface ISomeClass { ... }
class SomeClass : ISomeClass { ... }
class SomeOtherClass
{
...
public void Method(ISomeClass param) ...
...
}
[Test]
void SomeTest()
{
var someClassMock = CreateMock<ISomeClass >();
...
instanceOfSomeOtherClass.Method(someClassMock );
...
}
In other words, the interface only exists in order to decouple classes from each other (mainly during testing) and only one implementation of each interface tends to exist (ignoring mocks). Whilst this is sensible behaviour, it necessitates the creation of lots of interfaces, which only serve that purpose and clutter the code with a lot of replicated information. A solution would be to declare that an interface should be derived from the class by the compiler:
public class A => IA
{
public int X { get; }
public string F();
// other, non-public, stuff
}
With the compiler turning the above into:
public interface IA
{
int X { get; }
string F();
}
public class A : IA
{
public int X { get; }
public string F();
// other, non-public, stuff
}
This dramatically reduces the amount of "noise" in the code, simplifies maintenance (the one type need by edited to change both the class and interface), yet maintains the good "design to interfaces" practice.
Does this have to be a language feature? There's an automated refactoring in VS that extracts the interface for you and you could probably modify it to include an attribute-based link between the class and the interface so that the code won't compile if they begin to diverge.
Similarly I think code generation (#5561) could be used to construct an interface from the public members of a given class as well as partial class that specifies the implementation:
[AutoInterface("IA")]
public partial class A {
public int X { get; }
public string F();
}
generates:
public interface IA {
int X { get; }
string F();
}
public partial class A : IA { }
Beyond that this sounds like, at best, a tooling issue. Although if my interfaces were that entangled with my implementations I would suspect that something isn't right.
@HaloFour,
Most helpful comment
Similarly I think code generation (#5561) could be used to construct an interface from the public members of a given class as well as partial class that specifies the implementation:
generates:
Beyond that this sounds like, at best, a tooling issue. Although if my interfaces were that entangled with my implementations I would suspect that something isn't right.