Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
与D中的C#`readonly`关键字等价?_C#_Immutability_D - Fatal编程技术网

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

与D中的C#`readonly`关键字等价?,c#,immutability,d,C#,Immutability,D,根据我在读D时的理解,当对变量使用immutable关键字时,必须在编译时知道变量的值,而C#的readonly不需要,并且readonly字段可以在类构造函数中使用非静态值进行赋值。这在D中是可能的吗?我会将该字段声明为private,然后使用get访问器来读取它fwend的答案基本上是完全正确的,但是如果你想找一些不太详细的东西,你可以随时制作一个mixin来自动化它。以下未经测试的代码给出了总体思路: string readOnly(string typeName, string varN

根据我在读D时的理解,当对变量使用
immutable
关键字时,必须在编译时知道变量的值,而C#的
readonly
不需要,并且
readonly
字段可以在类构造函数中使用非静态值进行赋值。这在D中是可能的吗?

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

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++;
    }
}

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


由于对immutable似乎有一些困惑(从最初的问题和他伟大的评论中),我想我应该添加一个旁白

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

通常,
不可变(T)!=T
。然而,在某些情况下,它们可以隐式地相互转换。例如,如果T是一个没有“可变间接寻址”的类型。也就是说,如果我给一个函数传递一个
不可变(int)
,它们会收到一个副本——这个函数无法修改我传递的值,因为它是被复制的——如果类型系统不允许这样做,它只会令人讨厌,没有额外的保证,所以D类型系统允许这样做。但是,如果我传递一个不可变的(int*),调用函数可以更改它。在结构的情况下,如果任何成员都有可变间接寻址,那么结构也有可变间接寻址

因此,从理论上讲,回到更实际的问题上来,不可变值必须在编译时被知道,而且没有好的方法来创建它们,这一点都不是真的。但是,唯一的变异可能发生在构造函数内部。对于简单的标量类型,这一点非常明显:

immutable(int) i = rand();
但是像物体这样的东西呢?好吧,为了构造一个T型,我们使用

auto t = new T();
因此,为了构造我们使用的类型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
}
如您所见,变异可能发生在构造函数内部。您可以读取成员变量,但不能写入它们(immutable是可传递的;也就是说,如果父级不可更改,则每个成员(以及成员的每个成员)都将变为不可更改。您只能在方法标记为
const
时调用这些方法


我为离题的漫谈道歉,但我看到很多人似乎对这个主题感到困惑。

这是D2中最好的解决方案。我相信我的答案与当前版本的D不兼容。看看@Raphaël的答案。不需要在编译时知道immutable,只是没有任何好的方法来创建它们在运行时,没有强制转换。感谢您的深入解释。这消除了我对D中那些关键字的很多困惑(我想我混淆了D 1.0和2.0语义)。
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
}