在实现单例的连接池主类时,我遇到了一个不大不小的问题,下面是有问题的代码:
List<ConnectionStructon> connectionStructs = new List<ConnectionStructon>();
private static readonly Pool pool = new Pool();
private Pool()
{
Init();
}
private static Void Init()
{
//一些初始化操作,包括一些参数和按照配置文件生成一定数量的ConnectionStructon添加到List中
}
public static ConnectionStructon getConnectonStructon()
{
//得到连接构造体
}
上面的代码是有问题的,当我在测试类中使用getConnectionStructon()方法时,connectionstructs是没有被初始化的。
我知道静态方法和静态参数会先于构造函数被执行,但是在我看来,因为我在类的内部静态的实例化了他本身,所以当我调用getConnectionStructon方法时,私有化的构造函数应该已经被执行了,所以Init()应该是已经运行过,所以pool类的各种初始化操作应该是已经执行完毕了,但在实际测试时,这里是报错的,通过查看报错信息,我发现connectionStructs没有被初始化完全,里面并没有被加入连接。
于是经过查资料和各种测试,原来,静态变量会先于静态方法被执行,而在类的内部实例化它本身时,实际上,CLR会自动生成一个静态构造函数
static Pool(){}
所以,其实当执行private static readonly Pool pool = new Pool();这段代码时,并没有如我想象的执行了private Pool(),而是执行了一个我们看不见的static Pool();
知道了原因,所以我想到的解决方法是,重写静态构造函数
static Pool()
{
Init();
}
如此一来,这个问题算是解决了,可以在外部通过Pool.GetConnectionStructon()来得到连接,但是此处又引申出一个问题,因为当只有私有化的构造函数时,在外部是不能实例化Pool类的,在外部实例化Pool类:Pool pool = new Pool();时会报一个构造函数是受保护类型的异常,如此一来,就保证了Pool的单例化。但是当我将构造函数改为静态时,外部就可以实例化Pool类了,这违反了单例的原则,虽说在本项目中,Pool是否单例并不重要,只要可以共享ConnectionStructons即可,但我看着不爽,继续查资料和测试,发现原来static Pool()和private Pool()是可以共存的,所以修改代码如以下所示:
/// <summary>
/// 单例模式的连接池
/// </summary>
static Pool()
{
Init();
}
private Pool(){}
问题解决。
结论,C#中,单例模式实现方法为:
//内部私有静态实例化
private static readOnly Class class = new Class();
//静态构造函数
static Class()
{
//一些操作
}
//私有化构造函数,防止类在外部被实例化
private Class(){}