d为何to管用,转换不管用
原文
我写了些代码,做了一些转换
实验.我发现有时,对比转换(cast)
,仅std.conv.to!
工作,我不知道为什么,因为我假设他们
是一样的.我有如下接口:
interface ICustomDrawable {
void render(sfRenderWindow* renderWindow);
}
及实现该接口的以下类:
class Button : ICustomDrawable {
...
override void render(sfRenderWindow* renderWindow) {
...
}
}
及使用自定义的(ICustomDrawable)
类:
class StackLayout : ICustomDrawable {
...
void addChild(T)(T child) {
static assert(is(T : ICustomDrawable), "Invalid type T for child");
...
}
...
ICustomDrawable[] _children;
}
有时,想要转换子(属性)
,则只有第二个示例
有效:
foreach (Button button; cast(Button[])(_boardSizeRow.children)) {
button.update(event, _renderWindow);
}
//第1,第2
foreach (Button button; to!(Button[])(_boardSizeRow.children)) {
button.update(event, _renderWindow);
}
运行第一个
代码示例时,得到了一个黑屏
,而第二个没有
.这很奇怪,因为向控制台写入"type"
时,他们是相同的.为什么?
你需要知道两件事
:
1
.隐式转换
接口引用为兼容
类引用时,生成
的指针
略有不同.
interface I {}
class C : I {}
void main()
{
C c = new C;
I i = c;
import std.stdio;
writeln(cast(void*) c); /*如:7F3C140A7000*/
writeln(cast(void*) i); /*如:7F3C140A7010*/
}
2
.从A
数组类型到B
数组类型的转换
是"按绘画类型"完成的.是重新解释
而不是转换
数组元素.
但是不能按类引用
重新解释引用接口
,因为指针
会错.你需要转换
数组的每个元素
(因而用'to'
).
但,记住,可在不使用转换
或std.conv
就,仅通过省略
正在迭代的变量类型
来完成foreach
:
import std.stdio, std.conv;
interface IDog {
void bark();
}
class Dog: IDog{
string s;
this(string _s){s = _s;}
void bark(){writeln(s);}
}
class List{
IDog[] dogs;
void add(T)(T d){ dogs ~= d; }
}
void main(){
auto d1 = new Dog("meaw!");
auto d2 = new Dog("wof!");
auto l = new List();
l.add(d1);
l.add(d2);
foreach(d; l.dogs){ // 未标记d类型
d.bark();
}
}
'foreach'
适合该情况,因为'bark'
是'IDog'
的方法.但'update'
不是,因此需要转换为'Button[]'
.
此时,你可如下转换
类型:
import std.stdio, std.conv;
interface IDog {
void bark();
}
class Dog: IDog{
string s;
this(string _s){s = _s;}
void bark(){writeln(s);}
void update(string _s){ s ~= " - " ~ _s; }
}
class List{
IDog[] dogs;
void add(T)(T d){ dogs ~= d; }
}
void main(){
auto d1 = new Dog("meaw!");
auto d2 = new Dog("wof!");
auto l = new List();
l.add(d1);
l.add(d2);
foreach(i,d; l.dogs){//用i来显示每次更新
(cast(Dog)d).update(to!string(i));
d.bark();
}
}
解释如下.
转换
仅改变"观察
到的类型",而"to"
则是深度转换
.观察:
import std.stdio;
import std.conv;
void main()
{
int[] ints = [1, 2, 3];
auto bytes1 = cast(ubyte[])(ints);
auto bytes2 = to!(ubyte[])(ints);
writeln(bytes1);
writeln(bytes2);
}
//结果:
[1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0]
[1, 2, 3]
to
对"真正"
类型转换非常有用
.可改变串宽
.最后,"to"
可解释串.如:
import std.stdio;
import std.conv;
void main()
{
int[] ints = to!(int[])("[1, 2, 3]");
writeln(ints);
}
//结果
[1, 2, 3]
To
非常方便,因为这是"一站式商店
":不管你想做什么:"to"
就可了.不需要混合/匹配
的调用atoi/itoa/encode/decode
等的.此外,它是安全
的:如果失败,to
会抛.如果溢出
,它也会抛:
import std.conv;
void main()
{
int a = 500;
ubyte b = cast(ubyte)(a);
//无问题,静默溢出
ubyte c = to!ubyte(a);
//运行时溢出异常
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现