3

I would like to ask for an advise. I am learning C# and I am always trying to reduce code duplication and I am struggling to find "best practice" in C#.

I am trying to use Default interface methods to implement as much reusable code as possible, which works fine for simple examples.

I have an issue if class is derived from generic interfaces with several types e.g. IComplex<T1,T2,T3>. Casting object to Generic Interface with many types makes code unreadable. My class is derived from more such complex Interfaces. Refer to the example below. Calling a method Foo() and Foo2() is unreadable:

        (complex as IComplex<int, string, decimal>).Foo();

Using a new line of code for casting is an option, but I would prefer to just use 'complex.Foo()' without the need to duplicate the code already written in `interface IComplex<T1,T2,T3>'.

Example of Interface and class

interface IComplex<T1,T2,T3>
{
    T1 Property1 { get; set; }
    T2 Property2 { get; set; }
    T3 Property3 { get; set; }

    void Foo()
    {
        // Default method
        // Do some complicated stuff with Property1-3
    }
}

interface IOtherInterface<T1,T2,T3>
{
    void Foo2()
    {
        // Default method
        // Do some complicated stuff 
    }
}


public class Complex<T1, T2, T3> : IComplex<T1, T2, T3>, IOtherInterface<T1, T2, T3>
{
    public T1 Property1 { get; set; }
    public T2 Property2 { get; set; }
    public T3 Property3 { get; set; }
}

"Unreadable" code

public void ComplexExample()
{
    Complex<int, string, decimal> complex = new Complex<int, string, decimal>();
    (complex as IComplex<int, string, decimal>).Foo();      // <<<< This is not easily Readable !!!
 (complex as IOtherInterface<int, string, decimal>).Foo2();      // <<<< This is not easily either Readable !!!
}

Desired behavior

I would like to call a method directly like: complex.Foo(); without the need to replicate the Foo code.

public void DesiredBehaviour()
{
    Complex<int, string, decimal> complex = new Complex<int, string, decimal>();
    complex.Foo();              // This would be nice, but it is is compile error
    complex.Foo2();              // This would be nice, but it is is compile error
}

Is there any way to reuse the IComplex Foo() method in the override class Foo() method ? I have tried to use static extension methods, but I wonder if something cleaner exists. It seems not right.

I am aware of following techniques to maximise code reuse:

  1. Inheritance
  2. Static Extension methods
  3. Default interface methods

Thanks for sharing your techniques

3
  • 3
    Hi @walter33, this might be a better fit for codereview.stackexchange.com because it isn't trying to fix a specific problem, but is a more general question around best practices. Stack overflow prefers questions with a clear answer, rather than more opinion based ones. It's a good question though, and I think it would be very welcome on codereview.SE. I hope this helps you if you don't get any answers here. Commented May 15, 2020 at 15:14
  • 1
    How about IComplex<int, string, decimal> complex = new Complex<int, string, decimal>(); complex.Foo(); Commented May 15, 2020 at 15:22
  • Hi Tim, I need to wait 40 minutes before sending question to codereview.stackexchange.com because I cannot send more than 1 question in 40 minutes time frame. Commented May 15, 2020 at 15:51

2 Answers 2

1

One way would be to type the variable as the interface:

public void DesiredBehaviour()
{
    IComplex<int, string, decimal> complex = new Complex<int, string, decimal>();
    complex.Foo();
}

Or even a factory method if this is a common requirement:

class Complex<T1, T2, T3> : IComplex<T1, T2, T3>
{
    private Complex() { }

    static IComplex<T1, T2, T3> Create() => new Complex<T1, T2, T3>();
}

Then you cold write:

var complex = Complex<int, string, decimal>.Create();
complex.Foo();
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for hints. I have edited the sample, because I was not 100% clear. I am aware of those methods, but I need class Complex to use methods from more interfaces and I would like to be able to create object once (without casting or using different factories).
1

you can keep the type of the variable as the interface and not as the class.

public void DesiredBehaviour()
{
    IComplex<int, string, decimal> complex = new Complex<int, string, decimal>();
    complex.Foo();              // This would be nice, but it is is compile error
}

1 Comment

I am aware of this approach, but I need to use complex object with methods from both interfaces: ``` complex.Foo(); complex.Foo2(); ```

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.