Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.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
如果所有内置类型在C#中都是不可变的,则不';这难道不意味着在给它们分配了一个新值之后,它们的内存位置应该改变吗?_C#_Immutability - Fatal编程技术网

如果所有内置类型在C#中都是不可变的,则不';这难道不意味着在给它们分配了一个新值之后,它们的内存位置应该改变吗?

如果所有内置类型在C#中都是不可变的,则不';这难道不意味着在给它们分配了一个新值之后,它们的内存位置应该改变吗?,c#,immutability,C#,Immutability,我正在努力理解C语言中可变和不可变类型的概念,我认为它们不能“就地”更改,只能创建新变量(同名?),并为其指定编辑值。这不意味着它应该有不同的内存位置吗?我在VS2015中尝试过,但似乎不是 unsafe { int a = 7; int* test = &a; Console.WriteLine(a); Console.WriteLine((int)test); a+=5; test = &a;

我正在努力理解C语言中可变和不可变类型的概念,我认为它们不能“就地”更改,只能创建新变量(同名?),并为其指定编辑值。这不意味着它应该有不同的内存位置吗?我在VS2015中尝试过,但似乎不是

unsafe
{
    int a = 7;
    int* test = &a;

    Console.WriteLine(a);                
    Console.WriteLine((int)test);
    a+=5;
    test = &a;
    Console.WriteLine(a);
    Console.WriteLine((int)test);
    Console.ReadKey();
}
它输出:

7
107604264
12
107604264

我认为这里的问题是你把变量和值混淆了。变量只是可以存储值(对于值类型)或值引用(对于引用类型)的位置的名称。就我们在这里讨论的目的而言,变量的存储方式/位置无关紧要,因为我们讨论的是值的不变性

将值“7”赋给整型变量时,该值“7”将始终为“7”。在你的代码中,除了“7”之外,你什么都做不到。如果它是可变的,这意味着什么?这就像将“7”改为“12”,然后将程序中以前包含“7”的所有其他变量改为包含“12”


如果改为查看不可变的引用类型(如“string”),这会更清楚一些。如果我设置了
a=“Test”
b=a
a=“Test2”
,b的值仍然是“Test”。通常不可能更改字符串的内容(通过偷偷访问私有内存等操作不违反不变量),因此我们称字符串值为immutable。您可以相信,一旦字符串引用存储到变量中,它所引用的字符串值将永远不会更改。

我认为这里的问题是您将变量与值混淆了。变量只是可以存储值(对于值类型)或值引用(对于引用类型)的位置的名称。就我们在这里讨论的目的而言,变量的存储方式/位置无关紧要,因为我们讨论的是值的不变性

将值“7”赋给整型变量时,该值“7”将始终为“7”。在你的代码中,除了“7”之外,你什么都做不到。如果它是可变的,这意味着什么?这就像将“7”改为“12”,然后将程序中以前包含“7”的所有其他变量改为包含“12”

如果改为查看不可变的引用类型(如“string”),这会更清楚一些。如果我设置了
a=“Test”
b=a
a=“Test2”
,b的值仍然是“Test”。通常不可能更改字符串的内容(通过偷偷访问私有内存等操作不违反不变量),因此我们称字符串值为immutable。您可以相信,一旦字符串引用存储到变量中,它引用的字符串值将永远不会更改

如果对象创建后其状态不变,则该对象是不可变的

这只是关于状态的问题,这就是问题所在。IMO可变性/不可变性与类型无关,而是与实例相关,因此实例是可变的或不可变的。通常,如果您声明类型是不可变的,则表示该类型的所有实例都是不可变的。混淆可能来自
reference
vs
value
类型,但通常,两者都可能是可变的或不可变的,尽管强烈建议保持
value
类型不变


实际上,没有人阻止您更改不可变类对象的引用。它仍然是不可变的,因为您实际上无法更改状态

//the state can be changed Mutable
Mutable m = new Mutable(1);
m.X = 2; 

//the state cannot be changed
Immutable obj1 = new Immutable(1);
Immutable obj2 = new Immutable(2);
obj1 = obj2;

如果对象创建后其状态不变,则该对象是不可变的

这只是关于状态的问题,这就是问题所在。IMO可变性/不可变性与类型无关,而是与实例相关,因此实例是可变的或不可变的。通常,如果您声明类型是不可变的,则表示该类型的所有实例都是不可变的。混淆可能来自
reference
vs
value
类型,但通常,两者都可能是可变的或不可变的,尽管强烈建议保持
value
类型不变


实际上,没有人阻止您更改不可变类对象的引用。它仍然是不可变的,因为您实际上无法更改状态

//the state can be changed Mutable
Mutable m = new Mutable(1);
m.X = 2; 

//the state cannot be changed
Immutable obj1 = new Immutable(1);
Immutable obj2 = new Immutable(2);
obj1 = obj2;


@JohnWu
int
是不可变的。每次都会分配一个新实例
a+=5
不会更改
a
中的
int
,而是分配+运算符的结果。在这个主题中,可能令人困惑的是有两个区别:可变与不可变以及值与引用类型。由于
int
是一种值类型,变量
a
的新值总是存储在同一个位置(
a
在内存中的位置)@RenéVogt,因此在引用类型不可变类型的情况下,新实例存储在新内存位置,但名称相同?那么可变变量类型和不可变变量类型之间到底有什么区别呢?它打断了我的大脑:作为旁注,我建议
test
的值保持不变,这在某种程度上是一个实现细节。你当然不应该依赖它。我怀疑这在很大程度上是堆栈上的变量的副作用。我不太确定这种“值类型是不可变的”说教是从哪里来的,理解不可变性是非常没有帮助的。我假设程序员认识到传递给方法的参数可以在不影响调用方参数值的情况下进行变异。但这与不变性无关,一切都与复制有关。如果这种说法有助于你更好地理解它,那么就忽略它吧。@mjwills我理解