值和引用类型混淆
Value and Reference types confusion
我访问了有关此主题的每个网站,并且在过去几天阅读了 Jon Skeets 关于 References and Values and Parameter passing 的文章。我理解了这两种类型的概念,它们代表什么以及值和引用参数的区别是什么是另一个规范。
我了解它的工作原理以及您可以如何使用它,但我不明白大家对这个话题的看法。你们都在那里说,例如 int
是一个值类型, string
是一个引用类型。但根据我的理解,类型基本上只取决于它们声明的 class 类型。
查看此代码片段以了解我的意思:
public struct IntHolder
{
public int number;
}
IntHolder first = new IntHolder();
first.number = 5;
IntHolder second = first;
first.number = 6;
现在 second.number
的值为 5。如果将 struct
更改为 class
,number
将充当引用类型,因此完全没有关系int
是一般的值类型,它只是 class 的类型。同样的例子也适用于 string
,等等......
显然,声明对象的 class 的类型设置了其对象的类型,或者我误解了一个核心概念。请纠正我并帮助我理解它的正确性,或者告诉我说 int
string
等背后的意义是什么......有一个特殊的类型,即使它们何时初始化并不重要,所以基本上总是。
这与您要更改的字段类型无关。这里相关的确实只是父类型的种类:
IntHolder first = new IntHolder();
IntHolder second = first;
根据 IntHolder
的种类,这有两种不同的效果:
对于值类型 (struct
),这会创建一个 copy。值类型对象的数据与对象同存,所以全部复制。这有点等同于:
IntHolder second = new IntHolder();
second.number = first.number;
// and all other fields (visible or not) are copied too
这意味着对 copied 值类型的字段的赋值将覆盖该值而不影响原始对象。这就像局部变量的行为方式:
var x = 5;
var y = 2;
y = 3; // this does not change x
然而,当类型是引用类型时,赋值second = first
只是复制引用。保留值的基础对象对于两者都是相同的。因此,对任何一个对象的更改都会影响另一个对象——因为没有 “其他”:它是同一个对象,只是被两个单独的变量引用。
回答评论中的后续问题:
How do I need to imagine it that an int
variable is a value type and string
is a reference type? I mean, so the int
variable directly contains the number and the string
variable is just like a pointer to a storage location of the string object?
是的,就是这样。引用的值基本上只是指向对象实际所在内存的指针,而值类型的值是整个对象本身。
这就是为什么将值类型作为方法的参数意味着当调用该方法时,将整个值类型对象复制到堆栈中以执行该方法。
一个类型是值类型并不意味着它的成员也都是值类型。例如,值类型内部的字符串成员实际存储的值仍然是对字符串对象的引用。同样,引用类型的实际内存将包含值类型的实际值,以及对引用类型的 other 内存位置的引用。
If the parent type always matter more than the objects types, what can I use the type of int and string for?
没有什么比另一个更重要。作为值或引用类型的对象仅影响该对象的存储方式。对于对象的成员,这是完全单独评估的。
Is it possible if you just have one class and a bunch of variables to set some of them just as a reference to another variable, for example int
variables.
您不能像在 C 中那样拥有值类型的引用指针,不。但是您可以引用字段,这些字段允许您改变值类型字段的值。例如:
class Test
{
private int field;
public void ShowExample()
{
// set the value
field = 12;
// call the method and pass *a reference* to the field
// note the special syntax
MutateField(ref field);
// the field, which is a value type, was mutated because it was passed as a reference
Console.WriteLine(field == 4);
}
private static void MutateField(ref int value)
{
value = 4;
}
}
我访问了有关此主题的每个网站,并且在过去几天阅读了 Jon Skeets 关于 References and Values and Parameter passing 的文章。我理解了这两种类型的概念,它们代表什么以及值和引用参数的区别是什么是另一个规范。
我了解它的工作原理以及您可以如何使用它,但我不明白大家对这个话题的看法。你们都在那里说,例如 int
是一个值类型, string
是一个引用类型。但根据我的理解,类型基本上只取决于它们声明的 class 类型。
查看此代码片段以了解我的意思:
public struct IntHolder
{
public int number;
}
IntHolder first = new IntHolder();
first.number = 5;
IntHolder second = first;
first.number = 6;
现在 second.number
的值为 5。如果将 struct
更改为 class
,number
将充当引用类型,因此完全没有关系int
是一般的值类型,它只是 class 的类型。同样的例子也适用于 string
,等等......
显然,声明对象的 class 的类型设置了其对象的类型,或者我误解了一个核心概念。请纠正我并帮助我理解它的正确性,或者告诉我说 int
string
等背后的意义是什么......有一个特殊的类型,即使它们何时初始化并不重要,所以基本上总是。
这与您要更改的字段类型无关。这里相关的确实只是父类型的种类:
IntHolder first = new IntHolder();
IntHolder second = first;
根据 IntHolder
的种类,这有两种不同的效果:
对于值类型 (struct
),这会创建一个 copy。值类型对象的数据与对象同存,所以全部复制。这有点等同于:
IntHolder second = new IntHolder();
second.number = first.number;
// and all other fields (visible or not) are copied too
这意味着对 copied 值类型的字段的赋值将覆盖该值而不影响原始对象。这就像局部变量的行为方式:
var x = 5;
var y = 2;
y = 3; // this does not change x
然而,当类型是引用类型时,赋值second = first
只是复制引用。保留值的基础对象对于两者都是相同的。因此,对任何一个对象的更改都会影响另一个对象——因为没有 “其他”:它是同一个对象,只是被两个单独的变量引用。
回答评论中的后续问题:
How do I need to imagine it that an
int
variable is a value type andstring
is a reference type? I mean, so theint
variable directly contains the number and thestring
variable is just like a pointer to a storage location of the string object?
是的,就是这样。引用的值基本上只是指向对象实际所在内存的指针,而值类型的值是整个对象本身。
这就是为什么将值类型作为方法的参数意味着当调用该方法时,将整个值类型对象复制到堆栈中以执行该方法。
一个类型是值类型并不意味着它的成员也都是值类型。例如,值类型内部的字符串成员实际存储的值仍然是对字符串对象的引用。同样,引用类型的实际内存将包含值类型的实际值,以及对引用类型的 other 内存位置的引用。
If the parent type always matter more than the objects types, what can I use the type of int and string for?
没有什么比另一个更重要。作为值或引用类型的对象仅影响该对象的存储方式。对于对象的成员,这是完全单独评估的。
Is it possible if you just have one class and a bunch of variables to set some of them just as a reference to another variable, for example
int
variables.
您不能像在 C 中那样拥有值类型的引用指针,不。但是您可以引用字段,这些字段允许您改变值类型字段的值。例如:
class Test
{
private int field;
public void ShowExample()
{
// set the value
field = 12;
// call the method and pass *a reference* to the field
// note the special syntax
MutateField(ref field);
// the field, which is a value type, was mutated because it was passed as a reference
Console.WriteLine(field == 4);
}
private static void MutateField(ref int value)
{
value = 4;
}
}