0

I have a static class containing several subclasses for managing different constants. Very different classes I want to implement the same properties depending only on the defined constants.

It looks like this:

public static class A
{
    public static class Subclass1
    {
        public const int Constant1 = 0;
        public const int Constant2 = 1;

        public static List<int> Elements
        { get { return new List<int> { Constant1, Constant2 }} }

        public static int Sum { get { return Elements.Sum(); } }
        public static int NegSum { get { return -Elements.Sum(); } }
    }

    public static class Subclass2
    {
        public const int Constant3 = 3;
        public const int Constant4 = 4;

        public static List<int> Elements
        { get { return new List<int> { Constant3, Constant4 }} }

        public static int Sum { get { return Elements.Sum(); } }
        public static int NegSum { get { return -Elements.Sum(); } }
    }
}

so that I can easily access them by

int a = A.Subclass1.Constant1;
List<int> b = A.Subclass1.Elements;
int c = A.Subclass1.Sum;

The code of the Properties Sum and NegSum is always the same. You see the problem: I need to include them for every subclass again. Is there any way to reuse the code of the properties without implementing them for every single class?

What I would like to do is something like:

public abstract class Base
{
    public abstract static List<int> Elements { get; }
    public static int Sum { get { return Elements.Sum(); } }
    public static int NegSum { get { return -Elements.Sum(); } }
}

public static class B
{
    public static class Subclass1 : Base
    {
        const int Constant1 = 0;
        const int Constant2 = 1;

        public override static List<int> Elements
        { get { return new List<int> { Constant1, Constant2 }} }

    }

    public class Subclass2 : Base
    {
        const int Constant3 = 0;
        const int Constant4 = 1;
        public override static List<int> Elements
        { get { return new List<int> { Constant3, Constant4 }} }
    }
}

Well, I know that in C# Inheritance like this doesn't work for static classes. Is there any other smart way to implement this?

Hackster
  • 157
  • 3
  • 10

3 Answers3

1

Maybe try implementing Subclass1 and Subclass2 without static keyword. Like this

public abstract class Base
{
public Base(params int[] elements)
{
this.Elements = new List<int>(elements);
}
public List<int> Elements { get; private set; }
public virtual int Sum { get { return Elements.Sum(); } }
public virtual int NegSum { get { return -Elements.Sum(); } }
}

public static class B
{
    public static class Subclass1 : Base
    {
        const int Constant1 = 0;
        const int Constant2 = 1;

        public Subclass1() : base(Constant1, Constant2){}    
    }

    public class Subclass2 : Base
    {
        const int Constant3 = 0;
        const int Constant4 = 1;
        public Subclass2() : base(Constant3, Constant4){}  
    }
}

Then add two static properties to class B

public static Subclass1 InstanceSubclass1 {get; private set}
public static Subclass2 InstanceSubclass2 {get; private set}

At the end add static constructor to class B

static B()
{
InstanceSubclass1 = new Subclass1 ();
InstanceSubclass2 = new Subclass2 ();
}

You can now access to your classes by using

B.InstanceSubclass1
1

What you are wanting will not be possible without some code duplication. C# doesn't handle inheritance with static the same way. While you can't override the static member of a super class, you can use new to hide and reimplement it. The downside to this is you lose the subtype contract that abstract provides, but if you really want your types to be "abstract" and have static members, you are pretty much SOL on that front.

public class Base 
{
    public static List<int> Elements { get; }
    public static int Sum(List<int> Elements) => Elements.Sum();
    public static int NegSum(List<int> Elements) => -Elements.Sum();
}

public static class B
{
    public sealed class Subclass1 : Base
    {
        const int Constant1 = 1;
        const int Constant2 = 2;

        public static new List<int> Elements
        { get => new List<int> { Constant1, Constant2 }; }
        public static new int Sum { get => Base.Sum(Elements); }
        public static new int NegSum { get => Base.NegSum(Elements); }

    }

    public sealed class Subclass2 : Base
    {
        const int Constant3 = 3;
        const int Constant4 = 4;
        public static new List<int> Elements
        { get => new List<int> { Constant3, Constant4 }; }
        public static new int Sum { get => Base.Sum(Elements); }
        public static new int NegSum { get => Base.NegSum(Elements); }
    }
}

An alternative is that you can use the singleton pattern to create the illusion that you are achieving what you want to achieve. As far as intellisense is concerned, this will produce the exact same effect of accessing the members like B.Subclass1.Sum. The downside being that this would also expose the _Subclass1 and _Subclass2 classes and pollute the namespace, but you will just have to decide if that is an acceptable trade-off.

public abstract class Base 
{
    public abstract List<int> Elements { get; }
    public int Sum { get => Elements.Sum(); }
    public int NegSum { get => -Elements.Sum(); }
}

public static class B
{
    public static _Subclass1 Subclass1 { get; } = new _Subclass1();
    public static _Subclass2 Subclass2 { get; } = new _Subclass2();
    
    public sealed class _Subclass1 : Base
    {
        const int Constant1 = 1;
        const int Constant2 = 2;

        public override List<int> Elements
        { get => new List<int> { Constant1, Constant2 }; }

    }

    public sealed class _Subclass2 : Base
    {
        const int Constant3 = 3;
        const int Constant4 = 4;
        public override List<int> Elements
        { get => new List<int> { Constant3, Constant4 }; }
    }
}
Abion47
  • 22,211
  • 4
  • 65
  • 88
0

You could use interfaces and an extension method if you didn't want to have a base class:

public interface IElementsHost
{
    List<int> Elements { get; }
}

public static class ElementsExtensions
{
    public static int Sum(this IElementsHost host) => host.Elements.Sum();
    public static int NegSum(this IElementsHost host) => -host.Elements.Sum();
}

public class Host : IElementsHost
{
     public const int Constant1 = 2;
     public const int Constant2 = 3;

     public List<int> Elements { get; } 
         = new List<int>(new int[]{ Constant1, Constant2 });
}


// client code
var host = new Host();
var sum = host.Sum();

If you wanted related subclasses to have such capabilities, you'd have to do it with composition. It would look like:

public static class OtherStaticClass
{
     public static ElementHost { get; } = new Host();

     static OtherStaticClass()
     {
         Host.Elements.Add(/* some constant, etc. */);
     }
}


// client code
var sum = OtherStaticClass.ElementHost.Sum();
Colin
  • 4,025
  • 21
  • 40