如何创建需等待实例生成后再初始化变量的类?(C#颜色管理场景)
解决方案:让子类访问父Colorset实例的其他Category成员
问题说明
你需要构建一个颜色管理系统,Colorset类包含General和Page两个子类,希望Page能访问所属同一个Colorset实例中General的成员,同时支持在实例化Colorset时灵活设置属性——未手动设置的属性自动关联General的对应默认值。
你的初始代码存在的核心问题:非静态的General实例成员无法被Page直接访问。
初始代码示例:
public class Colorset { public General General { get; set; } public Page Page { get; set; } } public class General { public Color Primary = Color.FromArgb("#399ed6"); public Color Secondary = Color.FromArgb("#fff"); public Color Text = Color.FromArgb("#000"); } public class Page { public Color TitleBar = General.Primary; // 无法访问非静态General的成员 public Color TitleBarText = General.Secondary; }
你期望的实例化方式:
var colorset = new() { General = new() { Primary = Color.FromArgb("#fff"), Secondary = Color.FromArgb("#000") }, Page = new() { TitleBar = Color.FromArgb("#123") // 未设置TitleBarText时默认使用General.Secondary的值 } };
可行实现方案
方案1:构造函数注入父Colorset实例
让Page持有所属Colorset的引用,通过构造函数传入,同时用属性的getter逻辑实现默认值关联:
public class Colorset { public General General { get; set; } = new General(); public Page Page { get; set; } // 构造时自动给Page传入当前Colorset实例 public Colorset() { Page = new Page(this); } } public class General { public Color Primary { get; set; } = Color.FromArgb("#399ed6"); public Color Secondary { get; set; } = Color.FromArgb("#fff"); public Color Text { get; set; } = Color.FromArgb("#000"); } public class Page { private readonly Colorset _parentColorset; private Color? _titleBarText; // 通过构造函数接收父Colorset实例 public Page(Colorset parent) { _parentColorset = parent; } public Color TitleBar { get; set; } public Color TitleBarText { get => _titleBarText ?? _parentColorset.General.Secondary; set => _titleBarText = value; } }
实例化时完全符合你的预期语法,未设置TitleBarText会自动取General.Secondary的值:
var colorset = new Colorset { General = new General { Primary = Color.FromArgb("#fff"), Secondary = Color.FromArgb("#000") }, Page = new Page(colorset) { TitleBar = Color.FromArgb("#123") // TitleBarText自动使用General.Secondary的值 } };
方案2:在Colorset中添加同步逻辑
如果不想让Page持有父实例引用,可以在Colorset的属性setter中添加默认值同步逻辑:
public class Colorset { private General _general = new General(); private Page _page = new Page(); public General General { get => _general; set { _general = value; // 若Page的TitleBarText未设置,同步General的Secondary值 if (_page.TitleBarText == default) { _page.TitleBarText = _general.Secondary; } } } public Page Page { get => _page; set { _page = value; // 若Page的TitleBarText未设置,同步当前General的Secondary值 if (_page.TitleBarText == default) { _page.TitleBarText = _general.Secondary; } } } } public class General { public Color Primary { get; set; } = Color.FromArgb("#399ed6"); public Color Secondary { get; set; } = Color.FromArgb("#fff"); public Color Text { get; set; } = Color.FromArgb("#000"); } public class Page { public Color TitleBar { get; set; } public Color TitleBarText { get; set; } }
这种方式的优势是Page无需感知父实例,但要注意:如果后续General.Secondary更新,Page.TitleBarText不会自动同步,适合不需要实时更新的场景。
方案3:延迟加载实时绑定
如果需要属性值实时同步(比如General.Secondary更新后,Page.TitleBarText自动跟着变),可以用Func<T>实现延迟获取:
public class Colorset { public General General { get; set; } = new General(); public Page Page { get; set; } public Colorset() { // 给Page传入获取General实例的委托 Page = new Page(() => General); } } public class Page { private readonly Func<General> _getGeneral; private Color? _titleBar; private Color? _titleBarText; public Page(Func<General> getGeneral) { _getGeneral = getGeneral; } public Color TitleBar { get => _titleBar ?? _getGeneral().Primary; set => _titleBar = value; } public Color TitleBarText { get => _titleBarText ?? _getGeneral().Secondary; set => _titleBarText = value; } }
这种方案下,未设置的属性会实时读取General的最新值,完全满足动态关联的需求。
内容的提问来源于stack exchange,提问作者VC JS
相关产品推荐
相关产品推荐

