Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

inheritance of abstract class with static property in C#

Short version:

I have an abstract class A. It has a method that needs to know the value of a static class property that is specific to each subclass. The name and type is the same, just the value can be unique for each subclass.

Can I define this static property in the base class A to be able to access it with methods defined in A, but keeping the property's values of different subclasses unrelated?

Or how would I implement something like that?


Long version:

Let's say I have an abstract base class for data models. It has a public property Id (Int32).

I would like to implement a constructor in the base class that generates a new ID based on the last assigned ID for objects of a subclass.

The reason is that the real IDs are assigned automatically by the database, but each data model object already has to have a unique ID when it gets constructed without being written to the database yet. As the database assigns only positive integers as ID, my plan is to assign newly created data model objects a temporary, unique negative ID. As soon as the object gets written, the ID will get changed to the real one.

As I have quite a few different data model classes all deriving from my abstract base class, I thought it would be good to include that functionality there to not duplicate it. But each subclass has to have their own counter that points to the next free negative ID, as the different classes' IDs are unrelated.

So I need a static property in each subclass storing this class' last assigned temporary ID, but the mechanism to assign it is always the same and could be implemented into the abstract base class' constructor. However, I can't access a property from the base class that has to be implemented by the subclasses, which means I have to define it in the base class. But will this static property then be global for all subclasses, which is not what I want?

How can I implement this temporary ID counter the most elegant way?

Simplified code example:

public abstract class ModelBase
{
    public Int32 Id { get; set; }
    protected static Int32 LastTempId { get; set; } = 0;

    public ModelBase()
    {
        Id = --LastTempId;
    }
}


public class Model1 : ModelBase
{
    public Model1 () : base ()
    {
        // do something model1-specific
    }
}

public class Model2 : ModelBase
{
    public Model2() : base()
    {
        // do something model2-specific
    }
}

If I implement it like this, I fear that for both subclasses model1 and model2, the inherited static property LastTempId will be the same instance. But I want a separate counter for each subclass while still using it in the base class constructor.

like image 419
Byte Commander Avatar asked Apr 27 '16 13:04

Byte Commander


1 Answers

Short answer

The sub-classes cannot have different values for the static property because the static property is a property of the class, not of it's instances, and it's not inherited.

Long answer

You could implement a single counter on the abstract class as a static property and have one constructor of the abstract class using it.

EDIT: To save different counters for each sub-class you could use a static dictionary mapping a Type (sub-class) to a counter.

public abstract class A<T>
{
    public static Dictionary<Type, int> TempIDs = new Dictionary<Type, int>();

    public int ID { get; set; }

    public A()
    {
        if (!TempIDs.ContainsKey(typeof(T)))
            TempIDs.Add(typeof(T), 0);

        this.ID = TempIDs[typeof(T)] - 1;

        TempIDs[typeof(T)]--;
    }
}

public class B : A<B>
{

    public string Foo { get; set; }

    public B(string foo)
        : base()
    {
        this.Foo = foo;
    }
}

public class C : A<C>
{
    public string Bar { get; set; }

    public C(string bar)
        : base()
    {
        this.Bar = bar;
    }
}

B b1 = new B("foo");
B b2 = new B("bar");

C c1 = new C("foo");
C c2 = new C("foo");

b1.ID would be -1, b2.ID would be -2, c1.ID would be -1 and c2.ID would be -2

like image 168
Marco Scabbiolo Avatar answered Nov 01 '22 17:11

Marco Scabbiolo