我不明白为什么在 base class 中测试可能的接口是错误的

I don't understand why it is wrong to test for possible interfaces in a base class

我有一个抽象基础 class,它将在数百个派生 class 中使用,包括一个额外的抽象 class.

至少有 2 个属性(我们称它们为 Purpose 和 Description,都是字符串)将被添加到许多(但不是全部)具体派生的 classes 中,所以我创建了接口(IPurposeful和 IDescribable)以在需要时添加它们。目前一切顺利。

我想要一个单一的方法,我可以调用所有从我的基础 class 派生的 classes 来验证和更新描述 属性 如果它确实是可描述的,或者如果它不是 IDesribable,则 return 为真。我想要另一个与 validate/update 目的 属性.

类似的方法

我使用基础 class 中的一个方法实现了这一点,看起来像这样:

protected bool CheckDescription(bool modify = false)
{
    if (this is IDescribable ele)
    {
        var newDesc = GetCorrectDescription();

        UpdateDescription(newDesc, ele.Description, modify);

        return newDesc.Equals(ele.Description);
    }
    else
    {
        return true;
    }
}

SonarQube 将 "this is IDescribable" 检查标记为阻止程序(错误做法),我想知道为什么?我能想到的复制此功能的唯一其他方法是将基本方法更改为:

protected virtual bool CheckDescription(bool modify = false)
{
    return true;
}

然后将这个完全相同的方法添加到可能派生的数百个 classes:

protected override bool CheckDescription(bool modify = false)
{
    var newDesc = GetCorrectDescription();

    UpdateDescription(newDesc, Description, modify);

    return newDesc.Equals(Description);
}

现在这似乎是不好的做法。

编辑:更改了 is/as 模式以删除冗余

如果你的class可能IDescribable并且可能IPurposeful,那么给出它 合理的默认实现 这些接口可能是无操作的,并允许您的后代 classes 根据需要覆盖这些实现。

不需要类型检查。只需调用可覆盖的方法并遵守它们的结果。

如果您的 "optional" 接口不允许合理的空操作实现,请重新访问它们的定义。

现在您的基础 class 可以依赖接口,而不是测试它们。


您可能会在此处引入运行时错误 - 但对于需要实现特定接口且编译时不可检查的基本 class 方法也是如此。

我决定进一步探索扩展方法,发现它们可以满足我的特殊需求。我想标记将扩展方法视为正确答案的原始建议,但似乎找不到这样做的机制。

无论如何,扩展方法满足我的要求,能够在一个地方为大多数派生 类 定义默认算法,并仅在特定派生 类 中覆盖该行为 if/when .

缺点之一是我无法从 "override" 方法中调用 "base" 实现。这可能会导致将来需要重复代码,但幸运的是现在我还没有遇到这个问题。