为什么未密封类的未密封虚拟方法调用的顺序很重要?

问题描述 投票:1回答:2

为什么未密封类的未密封虚拟方法调用的顺序很重要?

我正在研究通过C#通过CLR书,并且遇到了以下摘录:

[当班级最初被密封时,将来可以更改为未密封破坏兼容性。但是,一旦某个班级被解封,您将永远无法将其更改为已密封未来,因为这将破坏所有派生类。 此外,如果未密封的类定义了任何未密封的虚拟方法,必须使用新的方法维护虚拟方法调用的顺序版本或将来有可能破坏派生类型。

有人能以一种万无一失的方式解释加粗显示的部分,并且(也许)提供一些例子吗?

我了解什么是密封/未密封的类/方法,我了解什么是虚拟方法。但是我不明白的是订购。摘录中指的是什么顺序?

c# clr virtual sealed sealed-class
2个回答
1
投票

这是关于更改源代码,而不是建立类层次结构。

C#中没有“ unsealed”关键字,您不能从密封的类派生一个类并以任何方式声明使密封的“ undone”。

您可以通过更改源代码来删除关键字“ sealed”-这是“ unsealing”,他们强调,这是一个不间断的更改。所有引用您的《守则》的图书馆都可以使用。

本书必须是关于代码审查或软件维护的,或者是关于程序库的演变,而不是关于编程的。


0
投票

在这种情况下,保持虚拟方法调用的顺序很重要:

class BaseClass
{
    public int Answer { get; protected set; }

    protected virtual void VM1() { Answer += 20; }
    protected virtual void VM2() { Answer += 10; }

    public void Init() { VM1(); VM2(); }
}

class DerivedClass : BaseClass
{
    private int _dividend;

    protected override void VM1() { Answer = _dividend = 20; }
    protected override void VM2() { Answer /= 10 }
}

现在让我们说您在某处有这个:

var baseObj = new BaseClass();
baseObj.Init();
int baseAnswer = baseObj.Answer;

var derivedObj = new DerivedClass();
derivedObj.Init();
int derivedAnswer = derivedObj.Answer;

[baseAnswer将包含30derivedAnswer将包含2

现在,假设Init()已更改,因此在VM2()之前调用了VM1()baseAnswer仍然包含30,所以一切看起来都不错。但是,derivedAnswer将包含20(原为2)!我认为这是本书在警告您的情况。

© www.soinside.com 2019 - 2024. All rights reserved.