12用d编程枚举
enum
用来定义命名常量值
.
if (operation == 1) {
result = first + second;
} else if (operation == 2) {
result = first - second;
} else if (operation == 3) {
result = first * second;
} else if (operation == 4) {
result = first / second;
}
1,2,3,4
就叫神数
,看不懂的.不好读
和维护
.
用枚举定义个名字后,就非常方便了.
enum TypeName { ValueName_1, ValueName_2, /* etc. */ }
加上基本类型,相当于一次定义几个基本类型编译时常量:
enum TypeName : base_type { ValueName_1, ValueName_2, /* etc. */ }
=...
,可在定义中加上,后面的默认加1. 这样:
enum NaturalConstant : double { pi = 3.14, e = 2.72 }
enum TemperatureUnit : string { C = "Celsius", F = "Fahrenheit" }
一下定义多个枚常量.
还可以enum int secondsPerDay = 60 * 60 * 24;
.编译时常数
enum fileName = "list.txt";
enum
就是编译时的意思.这些常量都是右值
,也叫清单常量
,相当于清单
文件里面的常量.
属性:.max
,.min
.
注意:
foreach (suit; Suit.min .. Suit.max) {//要缺一个
//foreach(suit;Suit.min .. Suit.max+1){//这样
//或者+1个
writefln("%s: %d", suit, suit);
}
这样枚举成员
import std.traits;
// ...
foreach (suit; EnumMembers!Suit) {//这样
writefln("%s: %d", suit, suit);
}
不能隐式转换
,避免出问题.
Suit suit = 1;
报编译错误.避免无效值成为特定枚举对象
.
但可从显式转过来:
suit = cast(Suit)1;
没问题.由程序员
保证值
是否有效.
一切重复,皆是祸害
.
常与不变,进出/共享
,都是类型限定符
enum
为编译时常量.
enum a = [ 42, 100 ];
writeln(a);
foo(a);
这里两个a值都是复制的.因为是编译时值
最好定义不变的enum a=f();
编译时执行,但确保不变,enum
就像个右值
一样.而不变
,则为运行时值
,有地址
但确保不变
.
编译时就像已知条件
,所有已知
的,都可以搞成编译时.
import std.stdio;
import std.random;
int readInt(string message) {
int result;
write(message, "? ");
readf(" %s", &result);
return result;
}
void main() {
enum min = 1;
enum max = 10;
immutable number = uniform(min, max + 1);
writefln("我在想%s和%s间数.",min, max);
auto isCorrect = false;
while (!isCorrect) {
immutable guess = readInt("你猜的是");
//上面可用int替换,不必不变
isCorrect = (guess == number);
}//基本上是猜不中的
writeln("对!");
}
不变,可以自动推导类型.类似auto/enum
.
import std.stdio;
void main() {
immutable inferredType = 0;
immutable int explicitType = 1;
immutable(int) wholeType = 2;
//添加显式类型
writeln(typeof(inferredType).stringof);
writeln(typeof(explicitType).stringof);
writeln(typeof(wholeType).stringof);
}
//
import std.stdio;
void main() {
int[] slice = [ 10, 20, 30, 40 ]; // 1
//immutable int[] slice = [ 10, 20, 30, 40 ];
//如是这句,则全变了,编译不过
halve(slice);
writeln(slice);
}
void halve(int[] numbers) {//这里是复制的切片// 2
foreach (ref number; numbers) {//切片,所以要变
number /= 2;
}
}
print(slice); // now compiles
// ...
void print(const int[] slice)
不变的变量可以在常
参数中用.//常,表示在这个函数中
不变.不变
是永远不变.
void print(const int[] slice) {//可变变量也可传进
slice[0] = 42; // 编译出错
(不变 为参数),则只能为不变
为参数.
引用类型,可用不变
不变具有传递性,这个调用不变,都要不变,不然,就有问题.
void main() {//坑人的问题
immutable int[] slice = [ 10, 20, 30, 40 ];
foo(slice);
}
void foo(const int[] slice) {//常,更有用,可不变
bar(slice); //必须是不变
}//要求const,更通用
void bar(immutable int[] slice) {
// ...
}
不喜欢或者.dup/或者.idup
.用模板.
import std.conv;
void foo(T)(T[] slice) {//模板,变可调用,不变也可
bar(to!(immutable T[])(slice));
//to,如果原来变量为不变,则不复制为不变,
}
强不变:
immutable int[] immSlice = [ 1, 2 ];
//元素/自身都不变,强不变
immSlice ~= 3; // 编译错误
immSlice[0] = 3; // 编译错误
immSlice.length = 1; // 编译错误
immutable int[] immOtherSlice = [ 10, 11 ];
immSlice = immOtherSlice; // 错误
//---
immutable(int)[] immSlice = [ 1, 2 ];
//只针对元素不可变,自身可变
immSlice ~= 3; // 可加
immSlice[0] = 3; // 编译错误
immSlice.length = 1; // 还可删
immutable int[] immOtherSlice = [ 10, 11 ];
immSlice = immOtherSlice;//
//总结:
immutable int[]a=[1]; /* 最强,元素切片都不能修改*/
immutable(int[])b = [1]; /* 同上*/
immutable(int)[] c = [1]; /*元素不可变,切片可变*/
immutable(char)[]
串,"hello"c
,字面量,
常,不变
具传递性.结构和类也一样.
常/不变
的结构/类
的所有元素
都是常/不变
.
.dup
与.idup
就是造适合不变/变
的数组的.
在要求串
时,只有符[]
,只好.idup
一个.
void foo(string s) {
// ...
}
void main() {
char[] salutation;
foo(salutation);//编译不过
foo(salutation.idup);//没问题
}
枚举数组/关联数组
会生成两份,所以,最好用不变的变量
枚,动,不变
都可以省略具体类型,因为可以推导
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现