Socket.close
现在是'this'
上的'域'
.
这不一定是坏事,就像close
也是域
一样,但是值得破坏
用户代码吗?好处不大.
是为了内存安全
,类析构器
不应构造器中
逃逸本(this)
,因此隐式
使类析构器域
.
问题
提交
因为标准套接字(std.socket)
在析构器中调用了close
,因此必须标记它为域
.
类析构器
的当前实现已破坏;甚至没有正确
实现D规范
!(规范说它们"总是虚的
",但它们从来都不是虚的
,但实现模拟
它),“析构器
结束时,自动调用父类
的析构器”,也只对了一半,调用rtFinalize
时,确实是,但用其他方式调用析构器
时,不会这样.
这对'@safe'
和其他静态
属性影响很大,它们根本不管用
!你不能在@safe
(或nogc
等)环境中调用'.destroy()'
,因为destroy
无法证明析构器
完全遵循这些规则.
如果遵循
规范,就可像其他虚方法
一样证明
它,因为子类
也必须遵循规则.但它将相当严格:
class A {
void dispose() @safe {}
}
class B : A {
override void dispose() @system
//编译错误,不能用`system`覆盖`safe`
//由于覆盖时,属性是继承的,因此不必写`'@safe'`
override void dispose() @safe {
super.dispose(); // 很好.
}
// 但能收紧吗?
override void dispose() @safe @nogc {
//签名`好`,可收紧限制,但是,规范说它必须调用父
super.dispose();//@nogc不能调用非@nogc的父
}
}
void destroy(T)(T t) {
t.dispose();
}
A a;
destroy(a);
//`因为`A.dispose`,推导为`@safe
B b;
destroy(b); //
//它最多也能做到`@safe`,因为`B.dispose`必须可调用`A.dispose`
//就像`rt_finalize`现在那样,即使在循环中让`destroy`调用`this.dtor();`,然后`this.dtor();`,它也最多只能推导出定义`析构器`的最顶层类,所实际指定的
强制调用'super.x()'
的"问题",是禁止析构器
收紧条件.它必须与父类的接口,属性
等完全匹配.
在"问题"
上加引号是因为这不一定是问题
!它工作得很好,只是你不能像在子类
中那样收紧,因为也要调用父链
.
目前实现没有按虚
处理析构器
,只是在调用
析构器时,假装是虚
.需要修复它,强制子类
继承父类属性
.
这样,可创建'@safe'
析构器.但是在此之前,必须从'@system'
环境中调用析构器
.即使在'@safe'
域中显式.destroy()
,析构器
也并不是@安全
的,因为静态
类型系统不能证明在子类型
中有析构器
,只能动态
知道,不要标记为'@system'
等.
那么,既然当前析构器已破坏'@safe'
,希望批量
修改问题.
终结器在实际
执行时非常麻烦,显然,没有GC
操作,因为它会死锁
,众所周知,不能访问GC
成员,因为可能已收集它们,但即使手动
管理成员也可能有问题.由于是从任意
线程调用终结器
,手动
管理成员引用了线本
数据,那么又惨了.注意,许多Win32GUI
句柄都是线本
的,所以也不要在终结器
中清理它们.没有
属性可帮助清理.除了pure
,这有点过头了,哈哈.
由于在套接字的析构器
中,标准套接字(std.socket)
调用了'close'
,所以也必须标记'close'
为'scope'
.
顺便,这也是不确定的;我希望Socket
有个释放
它的文件描述符的方法
,这样它就不再试图
关闭它了.这应该很简单.