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);//没问题
}

枚举数组/关联数组会生成两份,所以,最好用不变的变量
枚,动,不变都可以省略具体类型,因为可以推导

发布了381 篇原创文章 · 获赞 25 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/fqbqrr/article/details/104587356