检查实例是否已正确实例化的最佳方法

时间:2013-06-24 08:39:07

标签: c# exception constructor search-engine

所以我有一个关于检查对象是否使用特定构造函数实例化的问题。我有一个名为SearchWithTwoLevelCore的类,它是搜索引擎的一部分。它有一个像这样的构造函数:

public SearchWithTwoLevelCache(ISearchCore s, ICurrentTimeProvider tp)
    {
        //Initialize the two levels.
        S=s;
        lvl2 = TimeBoundedQueryCache(s.AsQueryDataSource, tp, TimeSpan(24,0,0));
        lvl1 = SizeBoundedQueryCache(lvl2, 10);


    }

其中S,lvl1和lvl2都是在类中声明的包含其他公共类对象的私有字段。然后我有一个我想要运行的公共方法,它位于SearchWithTwoLevelClass中,但首先我想检查一下用于制作SearchWithTwoLevelCache的构造函数是否是上面的方法,否则该方法将无法正常运行并抛出某种异常,如果它不是'吨。做这个的最好方式是什么?非常感谢提前!

3 个答案:

答案 0 :(得分:4)

这是Liskov Substitution Principle重要性的一个很好的例子。我非常喜欢this answer中使用的图像。

如果你的类有多个构造函数,并且你的方法的成功取决于调用了哪个构造函数,那么你有很多选择。

这里的主要问题是你的对象状态似乎取决于调用哪个构造函数;这不是最好的设计技术,因为它会导致整个班级的状态检查激增,无论您如何呈现您的实施。

1)将对象重构为较小的对象

这里的想法是你的构造函数应该只需要类需要运行的数据。如果你有多个构造函数,每个构造函数都需要不同数量的参数和数据,那么可以认为这个类实际上代表了几个不同的对象。

2)强制执行方法的数据要求。

public SearchWithTwoLevelCache(ISearchCore s, ICurrentTimeProvider tp)
{
    //Initialize the two levels.
    S=s;
    lvl2 = TimeBoundedQueryCache(s.AsQueryDataSource, tp, TimeSpan(24,0,0));
    lvl1 = SizeBoundedQueryCache(lvl2, 10);
}

可以说,这个状态实际上并不是类本身所要求的,因为如果它实际上是一个函数的先决条件,那么它就是函数本身的要求。这消除了歧义。

因此,您的课程可能会成为:

public SearchWithTwoLevelCache(ISearchCore s)
{
  S = s;
} 

public Whatever PerformTwoLevelSearch(ICurrentTimeProvider tp) { }

例如。

这里的想法是仅提供构造函数中对整个类的状态绝对必需的数据。

当然,您可以在方法级别实施检查并抛出异常,但对于使用您的课程的人来说,这可能会非常令人沮丧。他们怎么知道调用函数1,他们必须调用构造函数2并设置其他变量?他们如何知道使用哪个界面?这就是为什么使它成为函数的一个条件,使用和维护都要简单得多。

将来也会使这门课程变得困难。如果方法的成功依赖于首先调用其他几个方法或构造函数,那么重构和更改此逻辑也会强制所有客户端也进行更改。

答案 1 :(得分:1)

您可以在课程中设置public boolean property,并在特定的constructor中设置true。此属性的默认值可以是false

因此,如果对象是obj1,则可以在调用函数之前检查此布尔值。

if(obj1.public_property)
     // do function call

这只是一个解决方案。可能有比这更好的解决方案。

答案 2 :(得分:0)

快速解决方案(不好)将使用一个标志来指示调用哪个构造函数 - 稍后在代码中的任何位置检查它。

你需要的是F#中的Discriminated Unions。但是因为我们在C#中没有,所以你应该将你的类抽象为interface,然后为该接口提供不同的具体实现。

现在您可以使用方法重载(针对每个具体实现)来决定使用哪个具体实现。