c# – 如何设计一个类来防止循环依赖在构造之前调用派生成员?
发布时间:2020-12-15 08:18:11 所属栏目:百科 来源:网络整理
导读:(我将它标记为C#和 Java,因为它在两种语言中都是相同的问题.) 说我有这些课程 interface IKernel{ // Useful members,e.g. AvailableMemory,TotalMemory,etc.}class Kernel : IKernel{ private /*readonly*/ FileManager fileManager; // Every kernel has 1
(我将它标记为C#和
Java,因为它在两种语言中都是相同的问题.)
说我有这些课程 interface IKernel { // Useful members,e.g. AvailableMemory,TotalMemory,etc. } class Kernel : IKernel { private /*readonly*/ FileManager fileManager; // Every kernel has 1 file manager public Kernel() { this.fileManager = new FileManager(this); /* etc. */ } // implements the interface; members are overridable } class FileManager { private /*readonly*/ IKernel kernel; // Every file manager belongs to 1 kernel public FileManager(IKernel kernel) { this.kernel = kernel; /* etc. */ } } 这种设计的问题是,只要FileManager尝试在其构造函数内部执行任何内容(它可能合理地需要),它就会在潜在的子类实例上调用一个虚方法,该实例的构造函数尚未被调用. 在你可以定义真正的构造函数(而不是初始化程序,如C#/ Java)的语言中不会出现这个问题,因为在它们的构造函数被调用之前,子类甚至都不存在……但是在这里,会出现这个问题. 那么什么是最佳/适当的设计/实践,以确保不会发生这种情况? 编辑: 我不一定说我需要循环引用,但事实是内核和FileManager都相互依赖.如果您有关于如何在不使用循环引用的情况下缓解此问题的建议,那么这也很棒! 解决方法
就个人而言,我不喜欢循环引用.但是如果你决定离开它们,你可能会增加一些懒惰:
interface IKernel { // Useful members,etc. } class Kernel : IKernel { private readonly Lazy<FileManager> fileManager; // Every kernel has 1 file manager public Kernel() { this.fileManager = new Lazy<FileManager>(() => new FileManager(this)); /* etc. */ } // implements the interface; members are overridable } class FileManager { private /*readonly*/ IKernel kernel; // Every file manager belongs to 1 kernel public FileManager(IKernel kernel) { this.kernel = kernel; /* etc. */ } } 这里的懒惰让我们确保在查询FileManager实例时将完全初始化IKernel实现. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |