Home > Back-end >  Extract similar static members from derived classes elegantly
Extract similar static members from derived classes elegantly

Time:12-15

public class A : BaseClass
{
    public static readonly int Min = 0;
    public static readonly int Max = 20;
    public int Val { get; }
    public A(int val)
    {
        if (val < Min || val > Max)
            throw new ApplicationException("invalid val");
        Val = val;
    }
    public static A Add(A o1, A o2)
    {
        return new A(o1.Val   o2.Val);
    }
}

public class B : BaseClass
{
    public static readonly int Min = 0;
    public static readonly int Max = 100;
    public int Val { get; }
    public B(int val)
    {
        if (val < Min || val > Max)
            throw new ApplicationException("invalid val");
        Val = val;
    }
    public static B Add(B o1, B o2)
    {
        return new B(o1.Val   o2.Val);
    }
}

A and B are almost the same, so how to extract the static members (Min, Max, Add) and the constructor into BaseClass elegantly?

I tried generic constraints, but it requires a parameterless constructor.

CodePudding user response:

For now C# doesn't support static abstract members but, good news, .NET may support it in future: Static abstract members in interfaces . And

For .NET 6, you must enable preview features in your project to be able to mark an interface member as static abstract.

CodePudding user response:

Static members are underivable, use abstract/virtual properties.

public abstract class BaseClass
{
    public abstract int Min { get; }
    public abstract int Max { get; }
}

public class A : BaseClass
{
    public override int Min { get { return 0; } }
    public override int Max { get { return 20; } }
}

CodePudding user response:

Did not test, but I guess I'd go for Generics:

public abstract class BaseClass<T> where T:BaseClass<T>
{
    public int Val {get;}
    
    private Func<int, T> _tFactory;

    public BaseClass(int val, int min, int max, Func<int, T> factory)
    {
         Val = Guard( val, min, max, nameof(val) );
         _tFactory = factory;
    }

    private int Guard( int val, int min, int max, string varName )
    {
        if (val < min || val > max)
        {
            throw new ApplicationException($"Value of {varName} must be inside {min} to {max} (inclusive).");
        }
        return val;
    }

    public static T Add(T o1, T o2)
    {
         return o1.Add(o2);
    }
    
    private T Add(T o2)
    {
         return _tFactory(this.Val   o2.Val);
    }
}


public class A : BaseClass<A>
{
    public static readonly int Min = 0;
    public static readonly int Max = 20;
    public A(int val) : base( val, Min, Max, i => new A(i) )
    {
    }
}

public class B : BaseClass<B>
{
    public static readonly int Min = 0;
    public static readonly int Max = 100;
    public B(int val): base( val, Min, Max, i => new B(i) )
    {
    }
}
  •  Tags:  
  • c#
  • Related