1

我知道这里已经在 SO 上问过类似的问题,但具体来说,我的问题涉及readonly通过在抽象类的构造函数中调用虚拟成员来设置字段的场景。

考虑以下抽象类:

public abstract class FooBase
{
    private readonly IDictionary<string,object> _readonlyCache;

    protected abstract IDictionary<string,object> SetCache();

    protected FooBase()
    {
        _readonlyCache = SetCache();
    }
}

问题:

1)这只是糟糕的设计吗?

2)有更好的设计吗?

我知道你可以声明 as 的实现者FooBasesealed这将确保只SetCache()调用正确的实现。我不喜欢的是没有办法强制实施者必须标记为sealed. 任何建议都非常受欢迎。

4

2 回答 2

4

如果可能的话,这绝对是要避免的——在构造函数中调用虚方法总是有点臭,因为你将在子类开始执行初始化之前执行代码——它的构造函数主体不会执行。无论子类是否密封,都是如此;你处于一个非常糟糕的境地。

您可能需要考虑让子类构造函数将缓存传递给构造函数:

public abstract class FooBase
{
    private readonly IDictionary<string,object> _readonlyCache;

    protected FooBase(IDictionary<string,object> cache)
    {
        _readonlyCache = cache;
    }
}

这样,直接子类就可以决定要做什么 - 例如,它可能是抽象的并从进一步派生的类中获取缓存,或者它可能构建自己的。

于 2013-09-24T15:21:38.563 回答
1

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();
于 2013-09-24T15:22:06.297 回答