Code review: statyczne pole w generycznej klasie

Dzisiaj króciutki przykład:

class ItemInfo<T>
{
    public string Name{get;set;}
    public T Value{get;set;}
    
    private static int AnyField;
}

Powyższy kod nie zawsze jest złym wzorcem ale bardzo często może nim być. Należy sobie zdać sprawę, że statyczne pole nie będzie tutaj tworzone dla każdego obiektu ItemInfo. Będzie one współdzielone wyłącznie przez takie same typy. Przykład ilustrujący działanie:

internal class Program
{
   private static void Main(string[] args)
   {
     var integerInfo=new ItemInfo<int>();
     var stringInfo = new ItemInfo<string>();
     var integerInfo2 = new ItemInfo<int>();

    integerInfo.UpdateField(10);
    stringInfo.UpdateField(20);
    integerInfo2.UpdateField(30);
    
    Console.WriteLine(integerInfo.GetStaticField()); //30
    Console.WriteLine(stringInfo.GetStaticField()); // 20!!!
    Console.WriteLine(integerInfo2.GetStaticField()); //30
   }
}

Sam ostatnio miałem podobny problem i po zastanowieniu się chwilkę, stwierdziłem, że faktycznie statyczne pole nie  jest potrzebne. Nie ma nic złego w statycznych polach, jeśli chcemy mieć osobny egzemplarz na każdą kombinację argumentów. To może być szczególnie nietypowy scenariusz, gdy mamy wiele parametrów:

class ItemInfo<T1,T2,T3,T4,T5>
{
}

Łatwo sobie wyobrazić ile kombinacji użytkownik może przekazać…

4 thoughts on “Code review: statyczne pole w generycznej klasie”

  1. Tak w uproszczeniu mozna przyjac, ze kazdy typ generyczny generuje nowa klase.
    ItemInfo i ItemInfowygeneruja 2 rozne klasy a co za tym idzie, statyczne pola rowniez sa osobne.

  2. Można rozwiązać ten “problem”. Pole statyczne należy przenieść do niegenerycznej klasy. Następnie generyczna klasa powinna z niej dziedziczyć. Dzięki temu pole będzie faktycznie współdzielone przez wszystkie instancje dla różnych typów T klasy ItemInfo. Nawiązując do przykładu z tematu, należałoby wprowadzić następujące modyfikacje:

    class ItemInfo
    {
    protected static int AnyField;
    }

    class ItemInfo : ItemInfo
    {
    public string Name {get;set;}
    public T Value {get;set;}
    }

    Uruchamiając program otrzymamy:
    30
    30
    30

  3. Niestety z postów usuwane są niektóre znaki 🙁 Zamiast cudzysłowów powinny być nawiasy trójkątne:

    class ItemInfo”T” : ItemInfo

    Tak samo w zdaniu: […] dla różnych typów T klasy ItemInfo”T”.

Leave a Reply

Your email address will not be published.