c# - 实现 IDisposable 是否与组合聚合相矛盾?
问题描述
在 UML组合聚合中,我倾向于使用IDisposable
接口/模式来强制“Child
没有就不能存在Parent
” - 要求组合要求:
public class Parent : IDisposable
{
private readonly _childs;
public IReadOnlyCollection<Child> Childs => _childs;
public Parent()
{
_childs = new List<Child>();
}
public Child CreateChild()
{
var child = new Child();
_childs.Add(child);
return child;
}
public void Dispose()
{
foreach (var child in _childs)
child.Dispose();
}
}
public class Child : IDisposable
{
internal Child() {}
public void Dispose()
{
//Cleanup object, imagine an idempotent implementation
}
}
到目前为止,一切都很好。但现在想象一下这段代码:
var parent = new Parent();
var child = parent.CreateChild();
child.Dispose();
//At this point parent.Childs contains a disposed child object
由于我目前在我开发的图书馆中面临这样的情况,我想到了几个问题:
- 可以吗,它
parent.Childs
包含一个(实际上)不可用的对象?- 如果是
- 你会忽略它,因为它是用户自己决定过早处置它吗?
- 如果不
- 关于如何在 C# 中处理子对象的过早处理,是否有某种最佳实践?我的第一个想法是在处置子对象时使用回调函数/委托将自己从活动实例列表中删除,但对我来说这听起来相当笨拙。
- 还有其他借口可以让我免去责任吗?
- 如果是
从架构的角度来看,主要问题是IDisposable
每个人都可以看到Child
. 隐藏它基本上意味着利用 OO 多态性并将处置能力提取到一个不可见的实现中。但是对于域模型中的许多类,这绝对是一个臃肿的因素,没有额外的好处。此外,它固有地将 UML 组合聚合解释为“Child
只能由”Parent
破坏,我认为这是不正确的:
public interface IChild
{
//Child methods
}
internal class Child : IChild, IDisposable
{
//See implementation above
}
public class Parent : IDisposable
{
public IReadOnlyCollection<IChild> Childs => _childs;
public IChild CreateChild()
{
var child = new Child();
_childs.Add(child);
return child;
}
}
解决方案
可以吗,它
parent.Childs
包含一个(实际上)不可用的对象?
是的,但你不应该再碰它。通常你会ObjectDiposedException
在处理时触摸它时抛出一个。
我的第一个想法是在处置子对象时使用回调函数/委托将自己从活动实例列表中删除,但对我来说这听起来相当笨拙。
确实笨拙而危险。想象一下,您有一组财务数据,突然一些对象被删除,因为一些开发人员错误地处置了一个对象。而是如上所述抛出异常。
剩下的问题是:子对象应该实现IDisposable
,还是应该有一个只有父类知道和可用的“dispose”方法?这种方法对我来说似乎更有意义。
推荐阅读
- excel - 如何过滤每周最后一条记录的数据
- mysql - InnoDB导致无法重启MySQL
- powershell - 对于 Azure 数据工厂,有没有办法使用 powershell 而不是 GUI 来“验证所有”?
- clang - 无法使用 lld-link.exe (Windows) 链接 C 运行时库 (libcmt.lib)
- c# - 在 Ajax 成功函数上调用控制器中的 Action 方法以呈现局部视图
- python - 如何避免每次使用 Selenium python 登录
- angular - 如何在ngrx Store上添加带有id的效果
- mysql - 在一个mysql查询中从多个表中选择数据
- jquery - TypeError: $ (...).bootstrapTable 不是函数
- sql - SQL查找先进后出时间(有重叠和多行)