用C#语言泛化单件模式
本人对于C#只能算是初学者,写此随笔,也只为和大家一起讨论,共同进步。
我看到过一些用C#语言泛化单件(Singleton)的文章和代码,里面有个问题,即用new来创建对象,比如类似下面这段代码:
{
_instance = new T();
}
要想让其工作,你必须让T的构造函数为public。但是,如果T的构造函数为public,那任何客户代码都可调用new T()。你无法用语言本身限制其只能被创建最多一次和只有一个全局访问点,这样也就无法保证你的单件成为“单件”。
C++里有友元(friend),T的构造函数可是设为non-public,然后用单件的模板类作为友元去访问它。用ACE的单件模板类ACE_Singleton时,就是如此实现。但C#没有友元。
CodeProject有篇文章:Generic Singleton Pattern using Reflection, in C#。作者用.Net反射机制实现了泛化的单件,重要的是它可以用具有non-public构造函数的public类来实例化。他用Type.GetConstructor来找到non-public的构造函数,并调用它来创建实例。他的代码如下(我去掉了异常处理部分):
instance = (T)constructor.Invoke(null);
我仿照它写了我自己的泛化Singleton,见下:
{
private static volatile T _instance;
private static object _lock = new object();
public static T Instance
{
get
{
if (_instance == null)
{
lock (_lock)
{
if (_instance == null)
{
Type type = typeof(T);
ConstructorInfo ctor;
ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
null, new Type[0], new ParameterModifier[0]);
_instance = (T)ctor.Invoke(new object[0]);
}
}
}
return _instance;
}
}
}
当使用它时,客户代码是这样的:
{
#region Constructor
private ZoomTool()
{
}
#endregion
#region Properties
......
public static ZoomTool Instance
{
get { return Singleton<ZoomTool>.Instance; }
}
#endregion
}
使用ZoomTool单件时代码是这样:
但是这种泛型单件有一个问题:我得到了Code Analysis的CA1000警告:“不要在泛型类型中声明静态成员(Do not declare static members on generic types)”。
于是我将泛型类Singleton<T>改为普通类,将其中的Instance函数改为GetInstance<T>泛型函数,写下了另一个泛化的单件。
{
private static class Storage<T> where T : class
{
internal static volatile T _instance;
}
private static object _lock = new object();
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")]
public static T GetInstance<T>() where T : class
{
if (Storage<T>._instance == null)
{
lock (_lock)
{
if (Storage<T>._instance == null)
{
Type type = typeof(T);
ConstructorInfo ctor;
ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
null, new Type[0], new ParameterModifier[0]);
Storage<T>._instance = (T)ctor.Invoke(new object[0]);
}
}
}
return Storage<T>._instance;
}
}
}
这时客户代码是这样的:
{
#region Constructor
private ZoomTool()
{
}
#endregion
#region Properties
......
public static ZoomTool Instance
{
get { return Singleton.GetInstance<ZoomTool>(); }
}
#endregion
}
但我得到了另一个Code Analysis警告CA1004:“泛型方法应提供类型参数(Generic methods should provide type parameter)”。
MSDN里不推荐压制这两个消息(SuppressMessage),我感觉是泛型技术里有些规则限制的。我不太明白为什么要提示这2个警告。希望有经验的人,能说说自己的理解。先谢过了!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?