繁体   English   中英

D中C#`readonly`关键字的等价物?

[英]Equivalent of C# `readonly` keyword in D?

根据我在阅读D时的理解,当在变量上使用immutable关键字时,变量的值必须在编译时知道,而C#的readonly不需要,并且readonly字段可以在类构造函数中使用non分配 - 静态价值观。 这可能在D?

在D2中,const成员只能在构造函数内初始化(或直接在类声明中初始化,但不能同时在两者中):

import io = std.stdio;

class A
{
    const int member;
    this(int nb)
    {
        this.member = nb;
    }
}

void main()
{
    A a = new A(12);
    io.writeln(a.member);
    //a.member = 14; //Error: can only initialize const member member inside constructor
}

由于关于不可变的问题似乎存在一些混淆(来自原始问题和he_the_great的评论),我想我会补充一点。

当你说immutable int i = 42 ,你说我不会被修改,而不是在编译时知道它的值。 immutable实际上是一个类型修饰符,并创建一个新类型。 immutable Timmutable(T)的简写。 immutable(T)创建一个永远不会变异的T,也就是说,如果你读取了值,然后调用一个函数,那么值就是相同的。 将此与const(T)进行比较,它提供了较弱的保证,即该类型的实例不会被修改,但有人可能对其他地方进行了可变访问,因此,如果您读取该值然后调用函数,则不能假设价值会是一样的。

通常, immutable(T) != T 然而,在某些情况下,它们可以隐含地相互转换。 例如,如果T是一种被认为没有“可变间接”的类型。 也就是说,如果我传递一个函数一个immutable(int) ,它们会收到一个副本 - 如果类型系统不允许,那么该函数无法修改我传递的值,因为它被复制了如果没有额外的保证就会很烦人,所以D型系统允许它。 但是,如果我传递一个immutable(int *),那么可以通过调用函数进行更改。 在结构的情况下,如果任何成员具有可变间接,那么结构也被称为具有它。

因此,为了摆脱理论并回到更实际的问题,根本不可能在编译时知道不可变值,并且没有好的方法来创建它们。 但是,唯一的突变可能发生在构造函数内部。 对于简单的标量类型,这很明显:

immutable(int) i = rand();

但是像对象一样呢? 好吧,构建我们使用的类型T.

auto t = new T();

所以要构造我们使用的类型immutable(T)

auto t = new immutable(T)();

这是一个更完整的小例子

class Useless
{
    int i;

    this(int i)
    {
        this.i = i;
    }
}

int main(string[] args)
{
    auto o = new immutable(Useless)(cast(int) args.length);
    //o.i = 17;  error
    return o.i;  // fine
}

如您所见,构造函数内部可能发生变异。 您可以读取成员变量,但不能写它们(不可变是传递性的;也就是说,如果父进程,每个成员(以及成员的每个成员)都变为不可变。只有当它们被标记为const才能调用方法。

我为偏离话题的漫无边际道歉,但我看到很多人似乎对这个话题感到困惑。

fwend的答案基本上是死的,但如果你正在寻找一些不那么冗长的东西,你可以随时制作一个mixin来自动化它。 下面未经测试的代码给出了一般的想法:

string readOnly(string typeName, string varName) {
    // Create a private variable that prepends an _ to the name and a 
    // public accessor named name.  
    return "private " ~ typeName ~ " _" ~ varName ~ ";\n" ~
           "public " ~ typeName ~ 
           "varName() @property { return _" ~ varName ~ ";\n";
}

用法:

class Foo {
    mixin(readOnly("int", "num"));

    void incNum() {
        _num++;
    }
}

我将该字段声明为私有,然后使用get访问器来读取它

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM