是否可以在C#中使用带有非默认构造函数的单例?
这是这个问题的一个细微差异: 我有一个类,它为它的构造函数接受参数。我希望使这个单例在初始化单例时使用参数,因此不需要在每次检索实例时传递参数 我的解决方案(不是很优雅)是使用一个是否可以在C#中使用带有非默认构造函数的单例?,c#,singleton,parameter-passing,C#,Singleton,Parameter Passing,这是这个问题的一个细微差异: 我有一个类,它为它的构造函数接受参数。我希望使这个单例在初始化单例时使用参数,因此不需要在每次检索实例时传递参数 我的解决方案(不是很优雅)是使用一个CreateInstance()static方法来获取参数并构造singleton实例。然后,我将使用另一个静态方法GetInstance(),该方法将是无参数的,以获取singleton实例。在代码中,我需要确保在调用GetInstance之前,逻辑调用CreateInstance。但是,我不能在编译时强制执行此操作
CreateInstance()
static方法来获取参数并构造singleton实例。然后,我将使用另一个静态方法GetInstance()
,该方法将是无参数的,以获取singleton实例。在代码中,我需要确保在调用GetInstance之前,逻辑调用CreateInstance
。但是,我不能在编译时强制执行此操作。但是,我可以在运行时通过在GetInstance
中抛出异常来检查它是否在CreateInstance
之前调用
我是否可以通过编译时强制实现这种行为?或者至少,有没有更好的方法来做同样的事情呢?在编译时没有办法这样做,因为这就像问编译器“你能证明在有多个线程的情况下,在执行代码Y之前,代码X永远不会被执行吗?”。这是不可能做到的 至于设计的运行时行为,我认为这是最好的 通过在singleton类中公开
Func
属性,可以使它稍微好一点。当有人请求单例实例而实例尚未创建时,您的类将调用此“工厂方法”来构造单例。如果工厂方法为null
,则抛出异常或(如果适用)使用某些默认参数构造
这实际上是将单例的构造推迟到第一次真正需要它时,所以这是一些改进。但基本原则是相同的
更新:
正如
LukeH
所指出的,这正是Lazy
所做的(仅限NET4)。如果可能,请使用该方法,而不是编写自己的方法。如果singleton对象不存在,您可以让GetInstance()
调用CreateInstance()
方法。我会这样做。您可能需要添加锁或其他东西以确保:
public class ClassA {
private static ClassA instance;
private int param;
private ClassA(int param) {
this.param = param;
}
public static ClassA getInstance() {
if (instance == null) {
throw new CustomException("Not yet initialised");
} else {
return instance;
}
}
public static void createInstance(int param) {
if (instance == null) {
instance = new ClassA(param);
}
}
}
在您的
GetInstance()
方法中,如果您的值为null,那么您为什么不调用CreateInstance呢?如果您的值为null,那么您就可以进行惰性初始化。在一个经典的单例中,真正的魔法发生在静态只读
中,它一经使用就创建实例:
public class MySingleton
{
private static readonly _instance = new MySingleton();
private MySingleton() {}
public static MySingleton Instance
{
get
{
return _instance;
}
}
}
如果要将参数传递给构造函数,则必须自己实现锁定(请注意,双If
sandwitch将lock
):
使用CreateInstance()作为惰性的加载器,并让GetInstance返回Lazy.Value(您可能希望创建一个设置为=thelazy.Value的静态只读字段,以确保CreateInstance()中只有一个条目)@user691226您是否可以编写一些代码来说明您是如何做到这一点的,我可能有一些指针。你不能这样做,因为GetInstance没有CreateInstance需要的参数。你能确定他需要什么,因为他需要将参数传递给
CreateInstance
函数。这并不能解决所问的问题。如果这些神奇的参数没有传递到GetInstance,那么他从哪里得到这些参数呢?因为没有任何参数传递到GetInstance,所以我认为他们在这一点上是已知的。问题已经解决了这一点:“我的解决方案(不优雅)是有一个CreateInstance()获取参数并构造singleton实例的静态方法。然后,我将使用另一个无参数的静态方法GetInstance(),以获取singleton实例。”感谢您的回复。我想我希望我可能错过了一种完全不同的方法来实现相同的行为,这种行为给了我编译时检查。你已经描述了Lazy
是如何工作的:@LukeH:谢谢你的提示,我到目前为止还没有使用过这种方法。是的,这是我已经拥有的代码。不幸的是,问题是我是否可以将此行为的运行时强制更改为编译时行为。但这似乎不可能。哦,对不起,我误解了你的问题。但是不,你不能。我认为这或多或少是唯一的方法。。。我从来没有想到过双if
结构,我花了大约一分钟才理解它。简单而有效。这是一个完全无用的构造,因为如果单例实例getter总是传递“Something”(或其他一些内部定义的值),那么myArg
就不是一个参数-至少对使用者来说不是这样-所以实际上这个类仍然有一个无参数的构造函数
public class MySingletonWithConstructor
{
private static _instance;
private static object _lock = new Object();
private MySingletonWithConstructor(string myArg)
{
// ... do whatever necessary
}
public static MySingletonWithConstructor Instance
{
get
{
if(_instance==null)
{
lock(_lock)
{
if(_instance==null) // double if to prevent race condition
{
_instance = new MySingletonWithConstructor("Something");
}
}
}
return _instance;
}
}
}