【问题标题】:Shared instances in Self-Referencing Singleton自引用单例中的共享实例
【发布时间】:2019-07-10 03:23:02
【问题描述】:

当我尝试如下定义自引用单例时:

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> { ... }

除了获得DerivedChildADerivedChildB 的单个单例实例外,只有一个Derived&lt;int&gt; 类型的单例实例在两个子类之间共享。

我宁愿没有DerivedChildADerivedChildB 直接从Singleton&lt;T&gt; 派生。那么我应该如何修改我的类声明以获得DerivedChildADerivedChildB 的单个单例实例(换句话说,Singleton&lt;DerivedChildA&gt;Singleton&lt;DerivedChildB&gt;)?


编辑:正如 Varun 所指出的,当参数 T 类型不同时,这种自引用单例的方法确实会产生唯一的单例实例,例如 with

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

但是我的项目需要 DerivedChildADerivedChildB 具有完全相同的泛型类型 Derived&lt;int&gt; ,不幸的是我无法更改此要求。 :(

【问题讨论】:

    标签: c# singleton self-reference


    【解决方案1】:

    让我们了解这里发生了什么。静态字段在真实类型的所有实例之间共享。泛型定义不是真正的类型;一旦您为泛型参数提供了具体的泛型类型参数,就会创建一个真正的类型。所以在这种情况下,只要你说:

    : Derived&lt;int&gt;

    或者即使你直接从 Singleton 继承:

    : Singleton&lt;int&gt;

    一旦为泛型定义生成类型,它的静态(在您的示例中为实例)字段将在所有派生类型之间共享

    这可以通过一个稍微不同的例子来证明,通过改变泛型参数 T 的参数。所以如果你有

    class DerivedChildA : Derived&lt;int&gt;

    class DerivedChildB : Derived&lt;decimal&gt;

    您将生成两个独立的真实类型作为基础,因此静态 Instance 字段对于 A 和 B 的实例也将是独立的。

    【讨论】:

    • 感谢您的回复!我明白你关于在 DerivedChild 类中使用泛型参数 T 类型来分隔实例的观点。到目前为止,这也是我一直使用这个 Singleton 的方式。但是,我最近不得不声明两个具有完全相同参数 T 类型的类,这导致了共享单例实例问题的弹出。
    • @nyaow 你能改变 Derived 从哪个子 A/B 继承吗?您可以将其声明为 Derived 和 DerivedChildA : Derived 其中 T2 将是最终类型,除了导致实际基类型不同之外没有其他用途。不是一个人想要的,但如果你不能改变基本架构,你就没有多少选择了。
    • 是的,我可以对 Derived 和 Singleton 进行更改。这听起来像是一种可行的方法。从技术上讲,我可以对基础架构进行更改。我唯一不能改变的部分是DerivedChildADeriedChildB 的功能。
    猜你喜欢
    • 2016-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-05
    相关资源
    最近更新 更多