I'm seeking a way to integrate additional functionality into various classes in C#. Focusing on a default implementation for interface methods was a good idea.
Consider the following class structure:
Class A is a base for classes B, C, and D.
Class E is a base for classes F, G, and H.
Class O is a base for classes P, Q, and R.
Among these, classes B, F, and P must implement the interface
IDoable
, which includes a method
X
that should be consistent across all implementing classes.
Here's a simplified example:
public class A
{ }
public class B : A, IDoable
{ }
public class C : A
{ }
public class D : A
{ }
public class E
{ }
public class F : E, IDoable
{ }
public class G : E
{ }
public class H : E
{ }
public class O
{ }
public class P : O, IDoable
{ }
public class Q : O
{ }
public class R : O
{ }
public interface IDoable
{
string X() => "I want to implement method X only once";
}
public class Test
{
public void Run()
{
string bx = new B().X();
string fx = new F().X();
string px = new P().X();
string result = bx == fx && bx == px ? "Same :)" : "Various :(";
}
}
However, there's a debate regarding whether using default implementations for interface methods is advisable in C#. Are there alternative approaches to achieve this functionality without relying on default implementations? Or
is using default implementations acceptable in this scenario?
Note: A, E, and O have no shared characteristics and are not related.
What I have tried:
Firstly, I refrained from implementing X directly in classes B, F, and P to avoid violating the
DRY principle. Given that X is meant to be identical across these classes, this approach seemed impractical, especially if X is lengthy.
Secondly, I created an extension method, which worked well for providing the X functionality:
public static class DoableExtensions
{
public static string X(this IDoable doable)
{
return "I want to implement method X only once";
}
}
However, this approach resulted in an empty
IDoable
interface, which violates the
"CA1040: Avoid empty interfaces" rule.
Lastly, I considered the
Decorator pattern, but I'm unsure how to implement it efficiently while maintaining adherence to the DRY principle. But it's possible this approach is the key solution.