gpt4 book ai didi

具有可触发初始化的 C# 单例模式

转载 作者:太空狗 更新时间:2023-10-29 20:31:44 25 4
gpt4 key购买 nike

我需要一个单例:

  • 是延迟加载的
  • 是线程安全的
  • 在构造时加载一些值
  • 这些值可以随时查询
  • 初始化可能发生在某个精确的时间,在查询开始之前——所以我必须能够以某种方式从外部触发它。当然,多次触发应该只初始化一次。

我使用 .NET 3.5。

我从 Jon Skeet 的 implementation 开始(第 5 版)使用静态子类:

public sealed class Singleton
{
IEnumerable<string> Values {get; private set;}
private Singleton()
{
Values = new[]{"quick", "brown", "fox"};
}

public static Singleton Instance { get { return Nested.instance; } }

private class Nested
{
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested()
{
}

internal static readonly Singleton instance = new Singleton();
}
}

这勾选了几乎所有方框,除了“从外部触发初始化”。由于实际的初始化发生在 ctor 内部,因此它不会发生多次。

如何做到这一点?

单例将这样使用:

public static void Main(){

//do stuff, singleton should not yet be initialized.

//the time comes to initialize the singleton, e.g. a database connection is available
//this may be called 0 or more times, possibly on different threads

Singleton.Initialize();
Singleton.Initialize();
Singleton.Initialize();

//actual call to get retrieved values, should work
var retrieveVals = Singleton.Instance.Values;

}

最佳答案

看起来你可以这样做:

public sealed class Singleton
{
IEnumerable<string> Values {get; private set;}
private Singleton(bool loadDefaults)
{
if (loadDefaults)
Values = new[]{"quick", "brown", "fox"};
else
Values = new[]{"another", "set", "of", "values"};
}

public static Singleton Instance { get { return Nested.instance; } }

public static void Initialize() {
Nested.Initialize();
}

private class Nested
{
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested()
{
}

internal static readonly Singleton instance = new Singleton(true);
private static object instanceLock = new object();
private static bool isInitialized = false;

public static void Initialize() {
lock(instanceLock) {
if (!isInitialized) {
isInitialized = true;
instance = new Singleton(false);
}
}
}

}
}

或者创建一个将被更新的实例:

public sealed class Singleton
{
IEnumerable<string> Values {get; private set;}
private Singleton()
{
Values = new[]{"quick", "brown", "fox"};
}

public static Singleton Instance { get { return Nested.instance; } }

private static object instanceLock = new object();
private static bool isInitialized = false;

public static void Initialize() {
lock(instanceLock) {
if (!isInitialized) {
isInitialized = true;
Instance.Values = new[]{"another", "set", "of", "values"};
}
}
}

private class Nested
{
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested()
{
}

internal static readonly Singleton instance = new Singleton();
}
}

第三个变体基于您的不可变注释和删除嵌套类注释:

public sealed class Singleton
{
IEnumerable<string> Values {get; private set;}
private Singleton()
{
Values = new[]{"quick", "brown", "fox"};
}

private static Singleton instance;
private static object instanceLock = new object();

public static Singleton Instance {
get {
Initialize();
return instance;
}
}

public static void Initialize() {
if (instance == null) {
lock(instanceLock) {
if (instance == null)
instance = new Singleton();
}
}
}
}

关于具有可触发初始化的 C# 单例模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6943311/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com