Разделяемые экземпляры в синглтоне с самообращением - PullRequest
1 голос
/ 10 июля 2019

Когда я пытаюсь определить самоссылающийся синглтон следующим образом:

class Singleton<T> where T : Singleton<T> { protected static T singletonInstance; ... }

Реализация синглтон-класса работает хорошо, когда я получаю его с использованием неуниверсального класса, такого как:

class Derived : Singleton<Derived> { ... }

Однако, когда я пытаюсь извлечь синглтон через универсальный класс, например, так:

class Derived<T> : Singleton<Derived<T>> { ... }

и затем реализую универсальные классы:

class DerivedChildA : Derived<int> { ... }
class DerivedChildB : Derived<int> { ... }

Вместо того, чтобы получать индивидуальный классэкземпляры синглтона DerivedChildA и DerivedChildB, есть только один экземпляр синглтона типа Derived<int>, общий для двух дочерних классов.

Я бы предпочел не иметь DerivedChildA и DerivedChildB для получения изSingleton<T> напрямую.Итак, как мне следует изменить объявления классов, чтобы получить отдельные экземпляры-одиночки DerivedChildA и DerivedChildB (другими словами, Singleton<DerivedChildA> и Singleton<DerivedChildB>)?


Редактировать: как указаноВарун, этот метод самоссылающихся синглетов действительно генерирует уникальные одноэлементные экземпляры, когда тип аргумента T отличается, например, с

class DerivedChildC : Derived<string> { ... }
class DerivedChildD : Derived<double> { ... }

Однако мой проект требует DerivedChildA и DerivedChildB, чтобы иметьточно такой же общий тип Derived<int>, и, к сожалению, я не могу изменить это требование.(

1 Ответ

0 голосов
/ 10 июля 2019

Давайте разберемся, что здесь происходит. Статическое поле является общим для всех экземпляров реального типа. Общее определение не является реальным типом; реальный тип создается, как только вы предоставите конкретный аргумент универсального типа для универсального параметра. Так что в этом случае это происходит, как только вы говорите:

: Derived<int>

или даже если вы наследуете от Singleton:

: Singleton<int>

После того, как тип сгенерирован для общего определения, его статическое поле (экземпляр в вашем примере) будет общим для всех производных типов

Это может быть подтверждено немного другим примером, изменив аргумент для универсального параметра T. Поэтому вместо этого, если у вас есть

class DerivedChildA : Derived<int>

И

class DerivedChildB : Derived<decimal>

У вас будет два отдельных реальных типа, сгенерированных в качестве базы, и, следовательно, поле статического экземпляра также будет отдельным для экземпляров как A, так и B.

...