0

Given the following classes:

public class Item
{
    public int id;
    public ItemStats s;

    public Item(int id)
    {
        this.id = id;
        s = AllStats.Dict[id];
    }

}

public class Derived : Item
{
    public DerivedStats s;

    public Derived(int id) : base(id)
    {
        s = (DerivedStats)AllStats.Dict[id];
    }

}

public class ItemStats
{
    public int stat1;
    public int stat2;
}

public class DerivedStats : ItemStats
{
    public int stat3;
}

static public class AllStats
{
    public static Dictionary<int, ItemStats> Dict =
        new Dictionary<int, ItemStats>();
}

Run with this:

public class Test
{
    static void Main(string[] args)
    {
        AllStats.Dict[0] = new ItemStats(); // initialize stats for id 0
        ItemStats s = AllStats.Dict[0];
        s.stat1 = 1;
        s.stat2 = 2;

        AllStats.Dict[1] = new DerivedStats(); // initialize stats for id 1
        DerivedStats d = (DerivedStats)AllStats.Dict[1];
        d.stat1 = 1;
        d.stat2 = 2;
        d.stat3 = 3;

        Item I = new Item(0); // item with id 0
        Derived D = new Derived(1); // derived with id 1
        Console.WriteLine(I.s.stat1);
        Console.WriteLine(D.s.stat3);
    }
}

The purpose is to have all statistics for these items in a static dictionary, because they don't need to be included as fields in every single item instance, since they are the same for all instances.

But the derived items can have different stats (additional fields in the statistics), so I have a derived type also for the ItemStats class.

The program runs, but I get a warning that s in Derived class is hiding s from the base class. The warning goes away if I use the new keyword but I lose polymorphism and I don't know if it can have bad consequences at runtime.

This works without warnings:

public class Item
{
    public int id;
    ItemStats _stats;
    public virtual ItemStats s => _stats;

    public Item(int id)
    {
        this.id = id;
        _stats = AllStats.Dict[id];
    }

}

public class Derived : Item
{
    DerivedStats _stats;
    public override DerivedStats s => _stats;

    public Derived(int id) : base(id)
    {
        _stats = (DerivedStats)AllStats.Dict[id];
    }

}

The only issue I have with this solution is that it uses a property, that is an additional function call every time I access it (and it's pretty often), so I assume it's slower than just accessing s as a field.

So I'm looking for a solution that is both as performant as possible and that doesn't cause warnings, field hiding and loss of polymorphism. Ideal would have been if it was possible to use virtual and override for a class field, but it doesn't compile.

mg979
  • 43
  • 5
  • _"so I assume it's slower than just accessing s as a field"_ - is it real problem in your app though? have you profiled it? Is it a bottleneck? – Guru Stron Jul 02 '22 at 21:25
  • No it's just an assumption. Is it wrong? I haven't benchmarked anything. About being a problem, maybe it's not, but I'm looking for the best solution performance-wise. – mg979 Jul 02 '22 at 21:28
  • "but I lose polymorphism" - there is no "polymorphism" around field `s`... Are you sure you put correct code in the question? (I assume you know that adding `new` *does not* change behavior of your code at all, it only makes it painfully obvious that there is shadowing going on and whoever uses that field is in for a nasty surprises) – Alexei Levenkov Jul 02 '22 at 23:23
  • https://stackoverflow.com/questions/159978/c-sharp-keyword-usage-virtualoverride-vs-new is where I got the bad opinion about using `new` in my code. But I'm not really sure it is bad for my use case, I just want to avoid surprises at runtime. In theory it should be ok because derived classes know what they're accessing, based on their ids. – mg979 Jul 02 '22 at 23:29
  • Also, the classes I wrote here are just bare-bones examples, but I can have polymorphism in actual code. – mg979 Jul 02 '22 at 23:36

0 Answers0