gpt4 book ai didi

c# - 需要按特定顺序处理对象 : is this a code smell?

转载 作者:太空宇宙 更新时间:2023-11-03 20:35:16 26 4
gpt4 key购买 nike

上下文

我正在使用具有工作区概念的 Winforms 应用程序 (.NET 3.5 SP1),它可以包含 n 个面板。每个面板(派生自 Panel)都有 View :

    .-----------------------.    |Workspace              |    |.--------.  .--------. |    ||Panel1  |  |Panel2  | |    ||.-----. |  |.-----. | |    |||View1| |  ||View2| | |    ||'-----' |  |'-----' | |    |'--------'  '--------' |    '-----------------------'

All panels get added to the this.Controls collection of the Workspace class (which derives from an UltraTabPageControl, an Infragistics GUI control). Each view is added to the Controls collection of their parent. So, when Dispose is called on the Workspace, the panels and views automatically get disposed, which is completely expected and desired.

We have another concept called a ViewManager. It keeps track of all the View controls in the workspace, and is in charge of maintaining a single "master" view. Whenever a View is created, it registers itself with this manager. This adds the View to a list, and then runs some logic to determine the new "master" view and then calls a Synchronize() method on each View.

The current design is that, whenever View.Dispose() is called, it unregisters itself from the ViewManager. This removes the View from the list, and then runs corresponding logic that checks for a new master, out of the remaining views.

The twist

When we are closing an entire workspace, there is one special Panel type that needs to be closed before other panels. So we have code in our Dispose method that looks like this:

protected override void Dispose(bool disposing)
{
var theSpecialPanel = GetSpecialPanel();
if (theSpecialPanel != null)
{
theSpecialPanel.Dispose();
}
base.Dispose(disposing);
}

如果我们去掉那段代码,那么其他面板可能会在theSpecialPanel之前被处理掉。这会导致检查要运行的新主面板的逻辑,在每个 View(包括此特殊面板)上调用 Synchronize()。这会抛出一个

“InvalidComObjectException:无法使用已与其底层 RCW 分离的 COM 对象。”

问题

这个设计是代码味道吗?强制特定对象先于其他对象被处置是不是很奇怪?

最佳答案

要求以特定顺序处理某些对象是完全合理的。请注意,终结器的一个主要限制是它们不能保证有关处置顺序的任何事情。考虑一个 Froboz9000Connection 对象(用于管理与 Froboz 9000 计算机的连接),该对象又包含一个用于实际通信的 SerialPort。在程序结束之前,它必须向远程机器发送特定的命令序列是必要的。正确的事件顺序是 Frobozz9000Connection 对象的 Dispose 方法将发送必要的命令序列,然后 Dispose SerialPort。如果先处理 SerialPort,Frobozz9000Connection 对象将无法发送正确的命令序列来通知远程机器不再需要其服务。

顺便说一句,这个问题是我不喜欢终结器的另一个(众多)原因之一。虽然终结器有时确实有用,但我认为在绝大多数情况下,简单地确保正确使用 Dispose 更为重要。

关于c# - 需要按特定顺序处理对象 : is this a code smell?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5279448/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com