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) )
{
}
}