当前位置: 首页 > 编程语言 > C#

SingletonswithTerminatorbutnotIDisposableshare

时间:2023-04-10 16:54:14 C#

SingletonswithTerminatorbutnotIDisposable这就是我在“CLRviaC#”、“EffectiveC#”和其他资源中对IDisposable和Finalizers所说的理解:虽然我理解并同意综上所述,有一种情况我认为打破这些规则是有意义的:负责非托管资源的单例类(例如提供对特定文件的单点访问)。我认为在单例上使用Dispose()方法总是错误的,因为单例实例应该在应用程序的生命周期内存在,如果任何客户端代码调用Dispose(),那么你就完蛋了。但是,您需要一个终结器,以便终结器可以在应用程序卸载时清理非托管资源。因此,使用没有实现IDisposable终结器的单例类对我来说似乎是一件合理的事情,但这种类型的设计与我理解的最佳实践背道而驰。这是一个合理的方法吗?如果不是,为什么不呢?什么是更好的选择?如果非托管资源仅在应用程序退出时释放,您甚至不必担心终结器,因为卸载过程应该为您处理。如果您有多个应用程序域并且您想要处理应用程序域卸载,这可能是一个问题,但您可能不需要关心这些问题。我会说这种设计可能不是正确的做法(并且会让你在发现你真的需要两个实例之前更难修复)在你的入口点创建对象(或延迟加载包装器对象)和通过在需要的地方传递代码,很清楚谁负责将它提供给谁,然后您可以自由地更改您的决定,只使用对其余代码没有太大影响的一个(使用你得到的东西)我首先提到了针对对象的设计模式及其后果并不总是影响每一个语言决策,即使是面向对象的语言。您当然可以找到用一种语言(Smalltalk)比用另一种语言(C++)更容易实现的经典设计模式。话虽如此,我不确定我是否同意单例实例只应在应用程序结束时处理的前提。在我读过的单例设计模式描述(或设计模式:可重用面向对象软件的元素)中,没有任何内容提到这是该模式的一个属性。单例应确保在任何时刻只存在该类的一个实例;这并不意味着只要应用程序存在,它就必须存在。我有一种感觉,在实践中,在应用程序的大部分生命周期中确实存在许多单例。但是,请考虑使用TCP连接与服务器通信的应用程序,但也可以以断开连接的模式存在。连接后,您需要一个单例来维护连接信息和连接状态。断开连接后,您可能希望保留相同的单例-或者您可以处理单例。虽然有些人可能会争辩说保留单例更有意义(我什至可能在其中),但设计模式本身没有任何东西可以阻止您处理它-如果重新连接,单例可以再次实例化,因为在那时刻没有实例存在。换句话说,您可以创建具有IDisposable的单例合乎逻辑的场景。只要您的终结器不调用任何其他托管对象(例如Dispose)上的方法,您应该没问题。请记住,最终确定顺序不是确定性的。也就是说,如果您的单例对象Foo持有对需要处置的对象Bar的引用,则您无法可靠地编写:~Foo(){Bar.Dispose();垃圾收集器可能已经收集了Bar。冒着踩到一堆OOgoo(即引发战争)的风险,使用单例的一种替代方法是使用静态类。虽然它可能会让您收到代码审查投诉和FxCop警告,但在没有IDisposable的情况下实现终结器本身并没有错。但是,在单例上执行此操作并不是捕获进程或AppDomain拆卸的可靠方法。冒着给出主观设计建议的风险:如果对象确实是无状态的,则将其设为静态类。如果它是有状态的,那么问为什么它是单例:你正在创建一个可变的全局变量。如果您正在尝试捕获应用程序,请在主循环退出时处理它。除了Singleton在任何特定情况下的适用性之外,我认为处理Singleton没有任何问题。结合惰性实例化,它只是意味着如果您暂时不需要资源,则释放该资源,然后在需要时重新获取它。如果你想创建一个带有终结器的单例,你应该有一个WeakReference的静态引用。这将需要一些额外的工作来确保访问器中的线程安全,但它将允许在没有人使用单例时对其进行垃圾收集(如果有人随后调用GetInstance()方法,他们将获得一个新实例)。如果您使用静态强引用,即使没有其他引用,它也会使单例实例保持活动状态。以上是C#学习教程:单人与终结者但不是IDisposable分享的全部内容。如果对大家有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。涉及侵权,请点击维权联系管理员删除。如需转载请注明出处: