在单例类中,有时需要处理该实例并清理该类及其成员。当然,我不能使用IDispossible
界面。
在setter
属性中使用GetInstance
并在使用特定实例完成后分配null是否是一种好习惯?还是要公开singleton
类中的静态函数以显式清除现有实例?
答案 0 :(得分:2)
TL; DR:
如果您需要释放非托管资源-在这种情况下,我们将使用IDisposable
,请实施IDisposable
并不要使类成为单例。
如果您没有非托管资源,而您需要的是单例,则将其设为单例,不要担心将东西设置为null的“ setter”。没必要。
您正在尝试完成两件事:将一门课程设为一次性课程并将其设为单身,并且您已经看到两者相处得不好。我会做相反的事情,而不是解雇IDisposable
并寻找释放托管资源的另一种方法。实现IDisposable
,但不要使类成为单例。
为什么?主要是因为通常还有其他方法可以强制只存在一个类的实例而不使它成为单例。例如,大多数依赖项注入容器,包括IServiceProvider
,都可以很容易地将依赖项注册为单例:
services.AddSingleton<ThingThatIOnlyWantOneOf>();
这并不意味着ThingThatIOnlyWantOneOf
实际上是一个单例。我们可以创建它的多个实例。我们只是表示我们只想创建一个实例,并一遍又一遍地使用它。
即使我们不使用任何IoC / DI容器,我们仍然可以限制我们创建的类的实例数量,而无需实际使它成为单例。 (而且,当我们意识到确实需要更多实例时,这使我们可以灵活地改变主意。)
现在如何将类写为单例 并使类变为一次性的问题已经消失。我们正在使用另一种方法来创建和重用该类的一个实例,并且该类可以是一次性的。
还值得注意的是,将某些内容设置为null与实现IDisposable
是不同的。
在完成对象引用后,我们通常不会将其设置为null,因为.NET Framework会为我们处理该问题。当不再有对象引用时,该对象将超出范围,然后垃圾回收器将其从内存中删除。所有这些事情都可以有效地发生,而无需我们做任何事情。这就是为什么在方法末尾看不到多余的代码行将对象设置为null的原因。
我们仅在类处理非托管资源(例如SQL连接或打开的文件流)时实现IDisposable
。这些类实际上必须做一些事情来释放他们的资源,我们希望它能尽快发生。
这意味着如果某些东西 did 需要是一次性的,那么仅将其设置为null并不能实现。我们实际上想调用Dispose()
。如果实际上不需要将其丢弃,则无论如何我们都无需将其设置为null。我们可以让它超出范围并收集垃圾。
因此,如果您担心需要“清除”某些内容或将某些内容设置为null,则可能不需要。 IDisposable
的存在是为了标记需要“清理”的内容。这是一种了解,如果某些不实现了该功能,那么我们就不必为此担心。 (否则,出于不确定性和不确定性,我们将把所有内容都设置为null,这不会那么有趣。)