简体   繁体   中英

C# Code reuse ( Default Interface Methods / Extensions )

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 eg 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'.

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
  4. IoC Frameworks ( I am not familiar with IoC yet)

Thanks for sharing your techniques

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
}

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM