通过抽象类构造函数中的虚拟成员分配只读字段
本文关键字:虚拟成员 分配 读字段 抽象类 构造函数 | 更新日期: 2023-09-27 18:32:32
我知道在SO上已经提出了类似的问题,但具体来说,我的问题涉及通过在抽象类的构造函数中调用虚拟成员来设置readonly
字段的情况。
考虑以下抽象类:
public abstract class FooBase
{
private readonly IDictionary<string,object> _readonlyCache;
protected abstract IDictionary<string,object> SetCache();
protected FooBase()
{
_readonlyCache = SetCache();
}
}
问题:
1)这只是彻头彻尾的糟糕设计吗?
2)有更好的设计吗?
我知道您可以将FooBase
的实现者声明为sealed
,这将确保只调用SetCache()
的正确实现。我不喜欢的是,没有办法强制实施者必须标记为sealed
。非常欢迎任何建议。
如果可能的话,这绝对是要避免的事情 - 在构造函数中调用虚拟方法总是有点臭,因为您将在子类执行初始化之前执行代码 - 它的构造函数主体不会执行。无论子类是否密封,都是如此;你处于一个根本上令人讨厌的境地。
您可能需要考虑让子类构造函数将缓存传递给构造函数:
public abstract class FooBase
{
private readonly IDictionary<string,object> _readonlyCache;
protected FooBase(IDictionary<string,object> cache)
{
_readonlyCache = cache;
}
}
这样,直接子类就可以决定做什么 - 例如,它可能是抽象的,并从进一步派生的类中获取缓存,或者它可以构造自己的缓存。
1)是的,这是糟糕的设计,因为你不能强迫一个实现者被密封。 (我不明白你怎么能合理地把这种设计决策强加给别人的代码;控制别人的抽象级别不是由你来决定的。
2)是:例如,使ReadOnlyCache
成为抽象或非抽象的属性,并在首次使用时调用抽象方法来获取其值:
private readonly IDictionary<string,object> _readonlyCache;
private IDictionary<string,object> ReadOnlyCache
{
get
{
return _readonlyCache ?? _readonlyCache = GetEmptyCache();
}
}
protected abstract IDictionary<string,object> GetEmptyCache();