Some guy asked me this question couple of months ago and I couldn't explain it in detail. What is the difference between a reference type and a value type in C#?
几个月前有人问了我这个问题,我无法详细解释。在c#中引用类型和值类型的区别是什么?
I know that value types are int
, bool
, float
, etc and reference types are delegate
, interface
, etc. Or is this wrong, too?
我知道值类型是int、bool、float等,引用类型是delegate、interface等,还是这也错了?
Can you explain it to me in a professional way?
你能以专业的方式给我解释一下吗?
14 个解决方案
#1
140
Your examples are a little odd because while int
, bool
and float
are specific types, interfaces and delegates are kinds of type - just like struct
and enum
are kinds of value types.
您的示例有点奇怪,因为虽然int、bool和float是特定类型,但接口和委托是类型类型——就像struct和enum是类型的值。
I've written an explanation of reference types and value types in this article. I'd be happy to expand on any bits which you find confusing.
在本文中,我对引用类型和值类型进行了解释。我很乐意对你们感到困惑的部分进行扩展。
The "TL;DR" version is to think of what the value of a variable/expression of a particular type is. For a value type, the value is the information itself. For a reference type, the value is a reference which may be null or may be a way of navigating to an object containing the information.
“TL;DR”版本是考虑特定类型的变量/表达式的值。对于值类型,值是信息本身。对于引用类型,该值是一个引用,该引用可能是null,也可能是导航到包含该信息的对象的一种方式。
For example, think of a variable as like a piece of paper. It could have the value "5" or "false" written on it, but it couldn't have my house... it would have to have directions to my house. Those directions are the equivalent of a reference. In particular, two people could have different pieces of paper containing the same directions to my house - and if one person followed those directions and painted my house red, then the second person would see that change too. If they both just had separate pictures of my house on the paper, then one person colouring their paper wouldn't change the other person's paper at all.
例如,把变量想象成一张纸。它可以写上“5”或“false”,但它不可能有我的房子……它必须有到我家的方向。这些方向相当于参考。特别是,两个人可以有不同的纸条,上面写着通往我家的相同方向——如果一个人按照这些方向把我家漆成红色,那么另一个人也会看到这种变化。如果他们在纸上都有我房子的不同照片,那么一个人涂色他们的纸就不会改变另一个人的纸。
#2
18
Value type:
Holds some value not memory addresses
保存一些值而不是内存地址
Example:
例子:
Struct
结构体
Storage:
储存:
TL;DR: A variable's value is stored wherever it is decleared. Local variables live on the stack for example, but when declared inside a class as a member it lives on the heap tightly coupled with the class it is declared in.
Longer: Thus value types are stored wherever they are declared. E.g.: an int
's value inside a function as a local variable would be stored on the stack, whilst an in int
's value declared as member in a class would be stored on the heap with the class it is declared in. A value type on a class has a lifetype that is exactly the same as the class it is declared in, requiring almost no work by the garbage collector. It's more complicated though, i'd refer to @JonSkeet's book "C# In Depth" or his article "Memory in .NET" for a more concise explenation.
一个变量的值被存储在它被分解的地方。例如,本地变量存在于堆栈上,但当在类中作为成员声明时,它将与声明在其中的类紧密耦合在堆上。长:因此值类型存储在声明的任何地方。例:函数中作为局部变量的int值将存储在堆栈中,而声明为类中的成员的in int值将与声明的类一起存储在堆中。类上的值类型具有与声明的类完全相同的lifetype,几乎不需要垃圾收集器进行任何工作。更复杂的是,我可以参考@JonSkeet的书“c# In Depth”或者他的文章“. net中的记忆”来进行更简洁的解释。
Advantages:
优点:
A value type does not need extra garbage collection. It gets garbage collected together with the instance it lives in. Local variables in methods get cleaned up upon method leave.
值类型不需要额外的垃圾收集。它与它所在的实例一起收集垃圾。方法中的局部变量在方法离开时进行清理。
Drawbacks:
缺点:
-
When large set of values are passed to a method the receiving variable actually copies so there are two redundant values in memory.
当一组大的值被传递给一个方法时,接收变量实际上是复制的,所以在内存中有两个冗余值。
-
As classes are missed out.it losses all the oop benifits
因为课程被错过了。它失去了所有oop的好处
Reference type:
Holds a memory address of a value not value
保存一个没有值的值的内存地址。
Example:
例子:
Class
类
Storage:
储存:
Stored on heap
存储在堆
Advantages:
优点:
-
When you pass a reference variable to a method and it changes it indeed changes the original value whereas in value types a copy of the given variable is taken and that's value is changed.
当你将一个引用变量传递给一个方法时,它会改变原来的值,而在值类型中,会取一个给定变量的副本,这就改变了值。
-
When the size of variable is bigger reference type is good
当变量的大小较大时,引用类型比较好。
-
As classes come as a reference type variables, they give reusability, thus benefitting Object-oriented programming
作为引用类型变量,类提供了可重用性,因此有利于面向对象编程
Drawbacks:
缺点:
More work referencing when allocating and dereferences when reading the value.extra overload for garbage collector
在分配和读取值时删除引用的工作更多。垃圾收集器的额外过载
#3
12
I found it easier to understand the difference of the two if you know how computer allocate stuffs in memory and know what a pointer is.
我发现,如果你知道计算机如何在内存中分配东西,知道指针是什么,就更容易理解两者的区别。
Reference is usually associated with a pointer. Meaning the memory address where your variable reside is actually holding another memory address of the actual object in a different memory location.
引用通常与指针相关联。也就是说,变量所在的内存地址实际上在不同的内存位置中保存了实际对象的另一个内存地址。
The example I am about to give is grossly over simplified, so take it with a grain of salt.
我即将给出的这个例子过于简单,所以我们还是持保留态度吧。
Imagine computer memory is a bunch of PO boxes in a row (starting w/ PO Box 0001 to PO Box n) that can hold something inside it. If PO boxes doesn't do it for you, try a hashtable or dictionary or an array or something similar.
想象一下,计算机内存是一行中的一堆PO Box(从w/ PO Box 0001到PO Box n),可以在其中存放一些东西。如果PO box没有为您做,请尝试hashtable或dictionary或数组或类似的东西。
Thus, when you do something like:
因此,当你做某事时:
var a = "Hello";
var =“你好”;
the computer will do the following:
计算机将执行以下操作:
- allocate memory (say starting at memory location 1000 for 5 bytes) and put H (at 1000), e (at 1001), l (at 1002), l (at 1003) and o (at 1004).
- 分配内存(假设从内存位置1000开始为5字节),并将H(在1000)、e(在1001)、l(在1002)、l(在1003)和o(在1004)放在一起。
- allocate somewhere in memory (say at location 0500) and assigned it as the variable a.
So it's kind of like an alias (0500 is a). - 分配内存中的某个地方(比如在位置0500)并将其作为变量a分配,这有点像别名(0500是a)。
- assign the value at that memory location (0500) to 1000 (which is where the string Hello start in memory). Thus the variable a is holding a reference to the actual starting memory location of the "Hello" string.
- 将该内存位置(0500)的值赋给1000(这是字符串Hello在内存中的起始位置)。因此,变量a持有对“Hello”字符串实际启动内存位置的引用。
Value type will hold the actual thing in its memory location.
值类型将在其内存位置保存实际的东西。
Thus, when you do something like:
因此,当你做某事时:
var a = 1;
var = 1;
the computer will do the following:
计算机将执行以下操作:
- allocate a memory location say at 0500 and assign it to variable a (the same alias thing)
- 分配一个内存位置,比如在0500分配给变量a(同样的别名)
- put the value 1 in it (at memory location 0500).
Notice that we are not allocating extra memory to hold the actual value (1). Thus a is actually holding the actual value and that's why it's called value type. - 将值1放入其中(在内存位置0500)。注意,我们没有分配额外的内存来保存实际的值(1),因此a实际上保存了实际的值,这就是为什么它被称为value type。
#4
8
This is from a post of mine from a different forum, about two years ago. While the language is vb.net (as opposed to C#), the Value Type vs. Reference type concepts are uniform throughout .net, and the examples still hold.
这是我两年前在另一个论坛上的帖子。虽然语言是vb.net(与c#相对),但是值类型和引用类型的概念在整个。net中是统一的,并且这些例子仍然成立。
It is also important to remember that within .net, ALL types technically derive from the base type Object. The value types are designed to behave as such, but in the end they also inherit the functionality of base type Object.
同样重要的是要记住,在。net中,所有类型都从技术上派生自基类型对象。值类型被设计成这样,但最后它们也继承了基类型对象的功能。
A. Value Types are just that- they represent a distinct area in memory where a discrete VALUE is stored. Value types are of fixed memory size and are stored in the stack, which is a collection of addresses of fixed size.
值类型就是——它们代表内存中存储离散值的不同区域。值类型具有固定的内存大小,并存储在堆栈中,堆栈是固定大小的地址的集合。
When you make a statement like such:
当你做这样的陈述时:
Dim A as Integer
DIm B as Integer
A = 3
B = A
You have done the following:
你已经做了以下工作:
- Created 2 spaces in memory sufficient to hold 32 bit integer values.
- 在内存中创建了两个足够容纳32位整数值的空间。
- Placed a value of 3 in the memory allocation assigned to A
- 在分配给a的内存分配中放置一个值3
- Placed a value of 3 in the memory allocation assigned to B by assigning it the same value as the held in A.
- 在分配给B的内存分配中放置一个3的值,方法是将其分配给与a中的值相同的值。
The Value of each variable exists discretely in each memory location.
每个变量的值离散地存在于每个内存位置。
B. Reference Types can be of various sizes. Therefore, they can't be stored in the "Stack" (remember, the stack is a collection of memory allocations of fixed size?). They are stored in the "Managed Heap". Pointers (or "references") to each item on the managed heap are maintained in the stack (Like an Address). Your code uses these pointers in the stack to access objects stored in the managed heap. So when your code uses a reference variable, it is actually using a pointer (or "address" to an memory location in the managed heap).
B.引用类型可以有不同的大小。因此,它们不能存储在“堆栈”中(请记住,堆栈是固定大小的内存分配的集合?)它们存储在“托管堆”中。对托管堆上每个项的指针(或“引用”)都在堆栈中维护(如地址)。您的代码使用堆栈中的这些指针来访问存储在托管堆中的对象。因此,当代码使用引用变量时,它实际上是使用指针(或“地址”指向托管堆中的内存位置)。
Say you have created a Class named clsPerson, with a string Property Person.Name
假设您已经创建了一个名为clsPerson的类,它具有string属性Person.Name
In this case, when you make a statement such as this:
在这种情况下,当你这样陈述时:
Dim p1 As clsPerson
p1 = New clsPerson
p1.Name = "Jim Morrison"
Dim p2 As Person
p2 = p1
In the case above, the p1.Name Property will Return "Jim Morrison", as you would expect. The p2.Name property will ALSO return "Jim Morrison", as you would Iintuitively expect. I believe that both p1 and p2 represent distinct addresses on the Stack. However, now that you have assigned p2 the value of p1, both p1 and p2 point to the SAME LOCATION on the managed heap.
在上面的例子中,p1。顾名思义,Name属性将返回“Jim Morrison”。p2。顾名思义,Name属性也将返回“Jim Morrison”。我认为p1和p2都表示堆栈上不同的地址。但是,既然已经为p2分配了p1的值,p1和p2都指向托管堆上的相同位置。
Now COnsider THIS situation:
现在考虑一下这种情况:
Dim p1 As clsPerson
Dim p2 As clsPerson
p1 = New clsPerson
p1.Name = "Jim Morrison"
p2 = p1
p2.Name = "Janis Joplin"
In this situation, You have created one new instance of the person Class on the Managed Heap with a pointer p1 on the Stack which references the object, and assigned the Name Property of the object instance a value of "Jim Morrison" again. Next, you created another pointer p2 in the Stack, and pointed it at the same address on the managed heap as that referenced by p1 (when you made the assignement p2 = p1).
在这种情况下,您已经在托管堆上创建了person类的一个新实例,它的指针p1位于引用该对象的堆栈上,并再次将对象实例的名称属性指定为“Jim Morrison”。接下来,您在堆栈中创建了另一个指针p2,并将它指向托管堆上与p1引用的地址相同的地址(当您创建assignement p2 = p1时)。
Here comes the twist. When you the Assign the Name property of p2 the value "Janis Joplin" you are changing the Name property for the object REFERENCED by Both p1 and p2, such that, if you ran the following code:
转折来了。当您为p2分配名称属性值“Janis Joplin”时,您正在更改p1和p2引用的对象的名称属性,这样,如果您运行以下代码:
MsgBox(P1.Name)
'Will return "Janis Joplin"
MsgBox(p2.Name)
'will ALSO return "Janis Joplin"Because both variables (Pointers on the Stack) reference the SAME OBJECT in memory (an Address on the Managed Heap).
Did that make sense?
这样做有意义吗?
Last. If you do THIS:
最后一次。如果你这样做:
DIm p1 As New clsPerson
Dim p2 As New clsPerson
p1.Name = "Jim Morrison"
p2.Name = "Janis Joplin"
You now have two distinct Person Objects. However, the minute you do THIS again:
你现在有两个不同的人对象。然而,当你再次这样做的时候:
p2 = p1
You have now pointed both back to "Jim Morrison". (I am not exactly sure what happened to the Object on the Heap referenced by p2 . . . I THINK it has now gone out of scope. This is one of those areas where hopefullly someone can set me straight . . .). -EDIT: I BELIEVE this is why you would Set p2 = Nothing OR p2 = New clsPerson before making the new assignment.
你现在把这两者都指向了“吉姆·莫里森”。(我不确定p2所引用的堆上的对象发生了什么事)。我认为现在已经超出了范围。这是一个有希望的人能让我明白的领域之一。-编辑:我相信这就是为什么在做新的作业之前,你要设置p2 = Nothing或者p2 = New clsPerson。
Once again, if you now do THIS:
再一次,如果你现在这样做:
p2.Name = "Jimi Hendrix"
MsgBox(p1.Name)
MsgBox(p2.Name)
Both msgBoxes will now return "Jimi Hendrix"
两个msgbox现在将返回“吉米·亨德里克斯”
This can be pretty confusing for a bit, and I will say one last time, I may have some of the details wrong.
这可能会让人有点困惑,我最后再说一次,我可能有些细节弄错了。
Good Luck, and hopefully others who know better than me will come along to help clarify some of this . . .
祝你好运,希望那些比我更了解的人也能来帮助澄清其中的一些……
#5
3
value data type and reference data type
值数据类型和引用数据类型。
1) value( contain the data directly ) but reference ( refers to the data )
1)值(直接包含数据),但引用(引用数据)
2) in value( every variable has its own copy) but
in reference (more than variable can refer to some objects)
2) in value(每个变量都有自己的拷贝)但是in reference (more than variable can refer to some objects)
3) in value (operation variable can`t effect on other variable ) but in reference (variable can affect other )
3) in value(操作变量不能影响其他变量),in reference(变量可以影响其他变量)
4) value types are(int, bool, float) but reference type are (array , class objects , string )
4)值类型是(int, bool, float),但引用类型是(数组、类对象、字符串)
#6
1
"Variables that are based on value types directly contain values. Assigning one value type variable to another copies the contained value. This differs from the assignment of reference type variables, which copies a reference to the object but not the object itself." from Microsoft's library.
基于值类型的变量直接包含值。将一个值类型变量分配给另一个值类型变量将包含的值复制。这与引用类型变量的赋值不同,引用类型变量将引用复制到对象,而不是对象本身。
You can find a more complete answer here and here.
你可以在这里和这里找到一个更完整的答案。
#7
1
Sometimes explanations won't help especially for the beginners. You can imagine value type as data file and reference type as a shortcut to a file.
有时候,解释对初学者没有帮助。可以将值类型想像为数据文件和引用类型作为文件的快捷方式。
So if you copy a reference variable you only copy the link/pointer to a real data somewhere in memory. If you copy a value type, you really clone the data in memory.
因此,如果你复制一个引用变量,你只复制链接/指针到内存中的某个地方的真实数据。如果复制一个值类型,那么实际上是在内存中克隆数据。
#8
0
This is probably wrong in esoterical ways, but, to make it simple:
这可能在深奥的方面是错误的,但是,简单地说:
Value types are values that are passed normally "by value" (so copying them). Reference types are passed "by reference" (so giving a pointer to the original value). There isn't any guarantee by the .NET ECMA standard of where these "things" are saved. You could build an implementation of .NET that is stackless, or one that is heapless (the second would be very complex, but you probably could, using fibers and many stacks)
值类型是通常“按值”传递的值(因此复制它们)。引用类型是通过“引用”传递的(因此提供一个指向原始值的指针)。没有任何。net ECMA标准保证这些“东西”被保存在哪里。你可以构建一个。net实现,它是无堆叠的,或者是无堆的(第二个会非常复杂,但是你可能可以使用纤程和许多栈)
Structs are value type (int, bool... are structs, or at least are simulated as...), classes are reference type.
结构是值类型(int, bool…)是结构体,或者至少被模拟为…),类是引用类型。
Value types descend from System.ValueType. Reference type descend from System.Object.
值类型源自System.ValueType。引用类型源自System.Object。
Now.. In the end you have Value Type, "referenced objects" and references (in C++ they would be called pointers to objects. In .NET they are opaque. We don't know what they are. From our point of view they are "handles" to the object). These lasts are similar to Value Types (they are passed by copy). So an object is composed by the object (a reference type) and zero or more references to it (that are similar to value types). When there are zero references the GC will probably collect it.
现在. .最后,您有了值类型、“引用对象”和引用(在c++中,它们将被称为指向对象的指针)。在。net中,它们是不透明的。我们不知道它们是什么。在我们看来,它们是对象的“句柄”)。这些持续时间类似于值类型(它们是通过复制传递的)。因此,对象是由对象(引用类型)和对它的零个或多个引用(类似于值类型)组成的。当没有引用时,GC可能会收集它。
In general (in the "default" implementation of .NET), Value type can go on the stack (if they are local fields) or on the heap (if they are fields of a class, if they are variables in an iterator function, if they are variables referenced by a closure, if they are variable in an async function (using the newer Async CTP)...). Referenced value can only go to the heap. References use the same rules as Value types.
(在“默认”实现的。net),值类型可以在堆栈上(如果他们是本地字段)或在堆上(如果他们是类的字段,如果他们在一个迭代器函数变量,如果变量引用的一个闭包,如果他们在一个异步函数变量(使用新的异步CTP)……)。引用的值只能到堆中。引用使用与值类型相同的规则。
In the cases of Value Type that go on the heap because they are in an iterator function, an async function, or are referenced by a closure, if you watch the compiled file you'll see that the compiler created a class to put these variables, and the class is built when you call the function.
值类型的情况下,堆上的,因为他们是在一个迭代器函数,一个异步函数,或者引用一个闭包,如果你观察你会发现编译器编译后的文件创建一个类来把这些变量,构建和类时调用的函数。
Now, I don't know how to write long things, and I have better things to do in my life. If you want a "precise" "academic" "correct" version, read THIS:
现在,我不知道怎么写长篇大论,我有更好的事情要做。如果你想要一个“精确的”“学术的”“正确的”版本,请阅读以下内容:
http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx
http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx
It's 15 minutes I'm looking for it! It's better than the msdn versions, because it's a condensed "ready to use" article.
我找了15分钟!它比msdn版本要好,因为它是一篇浓缩的“准备使用”文章。
#9
0
The simplest way to think of reference types is to consider them as being "object-IDs"; the only things one can do with an object ID are create one, copy one, inquire or manipulate the type of one, or compare two for equality. An attempt to do anything else with an object-ID will be regarded as shorthand for doing the indicated action with the object referred to by that id.
认为引用类型最简单的方法是将其视为“对象- id”;唯一可以用对象ID做的事情是创建一个、复制一个、查询或操作一个类型,或者比较两个以实现相等。尝试使用对象id执行任何其他操作将被视为使用该id引用的对象执行指示操作的简写。
Suppose I have two variables X and Y of type Car--a reference type. Y happens to hold "object ID #19531". If I say "X=Y", that will cause X to hold "object ID #19531". Note that neither X nor Y holds a car. The car, otherwise known as "object ID #19531", is stored elsewhere. When I copied Y into X, all I did was copy the ID number. Now suppose I say X.Color=Colors.Blue. Such a statement will be regarded as an instruction to go find "object ID#19531" and paint it blue. Note that even though X and Y now refer to a blue car rather than a yellow one, the statement doesn't actually affect X or Y, because both still refer to "object ID #19531", which is still the same car as it always has been.
假设我有两个变量X和Y类型的车——一个引用类型。Y恰好持有“对象ID #19531”。如果我说“X=Y”,会导致X保存“对象ID #19531”。注意,X和Y都不拥有汽车。这辆车,也被称为“object ID #19531”,被存放在其他地方。当我把Y复制到X时,我所做的就是复制ID号。现在假设我说x。color = colors。blue。这样的声明将被视为一种指示去寻找“object ID#19531”并将其涂成蓝色。请注意,尽管X和Y现在指的是一辆蓝色的汽车,而不是黄色的汽车,但这个语句实际上并不影响X或Y,因为这两个语句仍然指的是“object ID #19531”,它仍然和以前一样。
#10
0
Variable types and Reference Value are easy to apply and well applied to the domain model, facilitate the development process.
变量类型和引用值易于应用和很好地应用于域模型,便于开发过程。
To remove any myth around the amount of "value type", I will comment on how this is handled on the platform. NET, specifically in C # (CSharp) when called APIS and send parameters by value, by reference, in our methods, and functions and how to make the correct treatment of the passages of these values.
要消除关于“值类型”数量的任何误解,我将评论如何在平台上处理它。NET,特别是c# (CSharp),当调用api时,通过值、引用、方法和函数发送参数,以及如何正确处理这些值的段落。
Read this article Variable Type Value and Reference in C #
请阅读c#中的变量类型值和引用
#11
0
Suppose v
is a value-type expression/variable, and r
is a reference-type expression/variable
假设v是一个值类型表达式/变量,而r是一个引用类型表达式/变量。
x = v
update(v) //x will not change value. x stores the old value of v
x = r
update(r) //x now refers to the updated r. x only stored a link to r,
//and r can change but the link to it doesn't .
So, a value-type variable stores the actual value (5, or "h"). A reference-type varaible only stores a link to a metaphorical box where the value is.
因此,值类型变量存储实际值(5或“h”)。引用类型varaible只存储到具有该值的隐喻框的链接。
#12
0
Simply put, value types get passed by their value and reference types by their reference (memory address).
简单地说,值类型通过它们的值和引用类型(内存地址)传递。
This means that changes made to the value type parameters (the formal parameters) inside a called method will not reflect in the values from where the method was called (the actual parameters).
这意味着在一个被调用的方法中对值类型参数(形式参数)所做的更改不会反映在调用方法的值(实际参数)中。
But changes made to reference parameters inside a called method will reflect in changes to the variables declared in the calling method.
但是对被调用方法中的引用参数所做的更改将反映调用方法中声明的变量的更改。
That's a brief explanation. Refer to here to understand in detail about value types, reference types, and values type vs. reference type.
这是一个简短的解释。要详细了解值类型、引用类型和值类型与引用类型,请参阅这里。
#13
0
Value Type:
值类型:
-
Fixed memory size.
固定的内存大小。
-
Stored in Stack memory.
存储在栈内存中。
-
Holds actual value.
有实际价值。
Ex. int, char, bool, etc...
int, char, bool等…
Reference Type:
引用类型:
-
Not fixed memory.
不是固定的内存。
-
Stored in Heap memory.
存储在堆内存中。
-
Holds memory address of actual value.
保存实际值的内存地址。
Ex. string, array, class, etc...
字符串、数组、类等。
#14
0
There is not a single difference between value types and reference types, there are many little details that are stated explicitly by the standard and some of them are not easy to understand, especially for beginners.
在值类型和引用类型之间没有一个单独的区别,有许多小细节是由标准显式声明的,其中一些不容易理解,特别是对于初学者来说。
See ECMA standard 33, Common Language Infrastructure (CLI). The CLI is also standardized by the ISO. I would provide a reference but for ECMA we must download a PDF and that link depends on the version number. ISO standards cost money.
参见ECMA标准33,公共语言基础设施(CLI)。CLI也通过ISO进行标准化。我会提供一个参考,但是对于ECMA,我们必须下载PDF,这个链接取决于版本号。ISO标准成本钱。
One difference is that value types can be boxed but reference types generally cannot be. There are exceptions but they are quite technical.
一个区别是值类型可以被装箱,但是引用类型通常不能被装箱。有例外,但都是技术性的。
Value types cannot have parameter-less instance constructors or finalizers and they cannot refer to themselves. Referring to themselves means for example that if there is a value type Node then a member of Node cannot be a Node. I think there are other requirements/limitations in the specifications but if so then they are not gathered together in one place.
值类型不能有无参数的实例构造函数或终结器,也不能引用它们自己。引用本身意味着,例如,如果有一个值类型节点,那么节点的成员就不能是节点。我认为规范中还有其他的需求/限制,但是如果有,那么它们不会集中在一个地方。
#1
140
Your examples are a little odd because while int
, bool
and float
are specific types, interfaces and delegates are kinds of type - just like struct
and enum
are kinds of value types.
您的示例有点奇怪,因为虽然int、bool和float是特定类型,但接口和委托是类型类型——就像struct和enum是类型的值。
I've written an explanation of reference types and value types in this article. I'd be happy to expand on any bits which you find confusing.
在本文中,我对引用类型和值类型进行了解释。我很乐意对你们感到困惑的部分进行扩展。
The "TL;DR" version is to think of what the value of a variable/expression of a particular type is. For a value type, the value is the information itself. For a reference type, the value is a reference which may be null or may be a way of navigating to an object containing the information.
“TL;DR”版本是考虑特定类型的变量/表达式的值。对于值类型,值是信息本身。对于引用类型,该值是一个引用,该引用可能是null,也可能是导航到包含该信息的对象的一种方式。
For example, think of a variable as like a piece of paper. It could have the value "5" or "false" written on it, but it couldn't have my house... it would have to have directions to my house. Those directions are the equivalent of a reference. In particular, two people could have different pieces of paper containing the same directions to my house - and if one person followed those directions and painted my house red, then the second person would see that change too. If they both just had separate pictures of my house on the paper, then one person colouring their paper wouldn't change the other person's paper at all.
例如,把变量想象成一张纸。它可以写上“5”或“false”,但它不可能有我的房子……它必须有到我家的方向。这些方向相当于参考。特别是,两个人可以有不同的纸条,上面写着通往我家的相同方向——如果一个人按照这些方向把我家漆成红色,那么另一个人也会看到这种变化。如果他们在纸上都有我房子的不同照片,那么一个人涂色他们的纸就不会改变另一个人的纸。
#2
18
Value type:
Holds some value not memory addresses
保存一些值而不是内存地址
Example:
例子:
Struct
结构体
Storage:
储存:
TL;DR: A variable's value is stored wherever it is decleared. Local variables live on the stack for example, but when declared inside a class as a member it lives on the heap tightly coupled with the class it is declared in.
Longer: Thus value types are stored wherever they are declared. E.g.: an int
's value inside a function as a local variable would be stored on the stack, whilst an in int
's value declared as member in a class would be stored on the heap with the class it is declared in. A value type on a class has a lifetype that is exactly the same as the class it is declared in, requiring almost no work by the garbage collector. It's more complicated though, i'd refer to @JonSkeet's book "C# In Depth" or his article "Memory in .NET" for a more concise explenation.
一个变量的值被存储在它被分解的地方。例如,本地变量存在于堆栈上,但当在类中作为成员声明时,它将与声明在其中的类紧密耦合在堆上。长:因此值类型存储在声明的任何地方。例:函数中作为局部变量的int值将存储在堆栈中,而声明为类中的成员的in int值将与声明的类一起存储在堆中。类上的值类型具有与声明的类完全相同的lifetype,几乎不需要垃圾收集器进行任何工作。更复杂的是,我可以参考@JonSkeet的书“c# In Depth”或者他的文章“. net中的记忆”来进行更简洁的解释。
Advantages:
优点:
A value type does not need extra garbage collection. It gets garbage collected together with the instance it lives in. Local variables in methods get cleaned up upon method leave.
值类型不需要额外的垃圾收集。它与它所在的实例一起收集垃圾。方法中的局部变量在方法离开时进行清理。
Drawbacks:
缺点:
-
When large set of values are passed to a method the receiving variable actually copies so there are two redundant values in memory.
当一组大的值被传递给一个方法时,接收变量实际上是复制的,所以在内存中有两个冗余值。
-
As classes are missed out.it losses all the oop benifits
因为课程被错过了。它失去了所有oop的好处
Reference type:
Holds a memory address of a value not value
保存一个没有值的值的内存地址。
Example:
例子:
Class
类
Storage:
储存:
Stored on heap
存储在堆
Advantages:
优点:
-
When you pass a reference variable to a method and it changes it indeed changes the original value whereas in value types a copy of the given variable is taken and that's value is changed.
当你将一个引用变量传递给一个方法时,它会改变原来的值,而在值类型中,会取一个给定变量的副本,这就改变了值。
-
When the size of variable is bigger reference type is good
当变量的大小较大时,引用类型比较好。
-
As classes come as a reference type variables, they give reusability, thus benefitting Object-oriented programming
作为引用类型变量,类提供了可重用性,因此有利于面向对象编程
Drawbacks:
缺点:
More work referencing when allocating and dereferences when reading the value.extra overload for garbage collector
在分配和读取值时删除引用的工作更多。垃圾收集器的额外过载
#3
12
I found it easier to understand the difference of the two if you know how computer allocate stuffs in memory and know what a pointer is.
我发现,如果你知道计算机如何在内存中分配东西,知道指针是什么,就更容易理解两者的区别。
Reference is usually associated with a pointer. Meaning the memory address where your variable reside is actually holding another memory address of the actual object in a different memory location.
引用通常与指针相关联。也就是说,变量所在的内存地址实际上在不同的内存位置中保存了实际对象的另一个内存地址。
The example I am about to give is grossly over simplified, so take it with a grain of salt.
我即将给出的这个例子过于简单,所以我们还是持保留态度吧。
Imagine computer memory is a bunch of PO boxes in a row (starting w/ PO Box 0001 to PO Box n) that can hold something inside it. If PO boxes doesn't do it for you, try a hashtable or dictionary or an array or something similar.
想象一下,计算机内存是一行中的一堆PO Box(从w/ PO Box 0001到PO Box n),可以在其中存放一些东西。如果PO box没有为您做,请尝试hashtable或dictionary或数组或类似的东西。
Thus, when you do something like:
因此,当你做某事时:
var a = "Hello";
var =“你好”;
the computer will do the following:
计算机将执行以下操作:
- allocate memory (say starting at memory location 1000 for 5 bytes) and put H (at 1000), e (at 1001), l (at 1002), l (at 1003) and o (at 1004).
- 分配内存(假设从内存位置1000开始为5字节),并将H(在1000)、e(在1001)、l(在1002)、l(在1003)和o(在1004)放在一起。
- allocate somewhere in memory (say at location 0500) and assigned it as the variable a.
So it's kind of like an alias (0500 is a). - 分配内存中的某个地方(比如在位置0500)并将其作为变量a分配,这有点像别名(0500是a)。
- assign the value at that memory location (0500) to 1000 (which is where the string Hello start in memory). Thus the variable a is holding a reference to the actual starting memory location of the "Hello" string.
- 将该内存位置(0500)的值赋给1000(这是字符串Hello在内存中的起始位置)。因此,变量a持有对“Hello”字符串实际启动内存位置的引用。
Value type will hold the actual thing in its memory location.
值类型将在其内存位置保存实际的东西。
Thus, when you do something like:
因此,当你做某事时:
var a = 1;
var = 1;
the computer will do the following:
计算机将执行以下操作:
- allocate a memory location say at 0500 and assign it to variable a (the same alias thing)
- 分配一个内存位置,比如在0500分配给变量a(同样的别名)
- put the value 1 in it (at memory location 0500).
Notice that we are not allocating extra memory to hold the actual value (1). Thus a is actually holding the actual value and that's why it's called value type. - 将值1放入其中(在内存位置0500)。注意,我们没有分配额外的内存来保存实际的值(1),因此a实际上保存了实际的值,这就是为什么它被称为value type。
#4
8
This is from a post of mine from a different forum, about two years ago. While the language is vb.net (as opposed to C#), the Value Type vs. Reference type concepts are uniform throughout .net, and the examples still hold.
这是我两年前在另一个论坛上的帖子。虽然语言是vb.net(与c#相对),但是值类型和引用类型的概念在整个。net中是统一的,并且这些例子仍然成立。
It is also important to remember that within .net, ALL types technically derive from the base type Object. The value types are designed to behave as such, but in the end they also inherit the functionality of base type Object.
同样重要的是要记住,在。net中,所有类型都从技术上派生自基类型对象。值类型被设计成这样,但最后它们也继承了基类型对象的功能。
A. Value Types are just that- they represent a distinct area in memory where a discrete VALUE is stored. Value types are of fixed memory size and are stored in the stack, which is a collection of addresses of fixed size.
值类型就是——它们代表内存中存储离散值的不同区域。值类型具有固定的内存大小,并存储在堆栈中,堆栈是固定大小的地址的集合。
When you make a statement like such:
当你做这样的陈述时:
Dim A as Integer
DIm B as Integer
A = 3
B = A
You have done the following:
你已经做了以下工作:
- Created 2 spaces in memory sufficient to hold 32 bit integer values.
- 在内存中创建了两个足够容纳32位整数值的空间。
- Placed a value of 3 in the memory allocation assigned to A
- 在分配给a的内存分配中放置一个值3
- Placed a value of 3 in the memory allocation assigned to B by assigning it the same value as the held in A.
- 在分配给B的内存分配中放置一个3的值,方法是将其分配给与a中的值相同的值。
The Value of each variable exists discretely in each memory location.
每个变量的值离散地存在于每个内存位置。
B. Reference Types can be of various sizes. Therefore, they can't be stored in the "Stack" (remember, the stack is a collection of memory allocations of fixed size?). They are stored in the "Managed Heap". Pointers (or "references") to each item on the managed heap are maintained in the stack (Like an Address). Your code uses these pointers in the stack to access objects stored in the managed heap. So when your code uses a reference variable, it is actually using a pointer (or "address" to an memory location in the managed heap).
B.引用类型可以有不同的大小。因此,它们不能存储在“堆栈”中(请记住,堆栈是固定大小的内存分配的集合?)它们存储在“托管堆”中。对托管堆上每个项的指针(或“引用”)都在堆栈中维护(如地址)。您的代码使用堆栈中的这些指针来访问存储在托管堆中的对象。因此,当代码使用引用变量时,它实际上是使用指针(或“地址”指向托管堆中的内存位置)。
Say you have created a Class named clsPerson, with a string Property Person.Name
假设您已经创建了一个名为clsPerson的类,它具有string属性Person.Name
In this case, when you make a statement such as this:
在这种情况下,当你这样陈述时:
Dim p1 As clsPerson
p1 = New clsPerson
p1.Name = "Jim Morrison"
Dim p2 As Person
p2 = p1
In the case above, the p1.Name Property will Return "Jim Morrison", as you would expect. The p2.Name property will ALSO return "Jim Morrison", as you would Iintuitively expect. I believe that both p1 and p2 represent distinct addresses on the Stack. However, now that you have assigned p2 the value of p1, both p1 and p2 point to the SAME LOCATION on the managed heap.
在上面的例子中,p1。顾名思义,Name属性将返回“Jim Morrison”。p2。顾名思义,Name属性也将返回“Jim Morrison”。我认为p1和p2都表示堆栈上不同的地址。但是,既然已经为p2分配了p1的值,p1和p2都指向托管堆上的相同位置。
Now COnsider THIS situation:
现在考虑一下这种情况:
Dim p1 As clsPerson
Dim p2 As clsPerson
p1 = New clsPerson
p1.Name = "Jim Morrison"
p2 = p1
p2.Name = "Janis Joplin"
In this situation, You have created one new instance of the person Class on the Managed Heap with a pointer p1 on the Stack which references the object, and assigned the Name Property of the object instance a value of "Jim Morrison" again. Next, you created another pointer p2 in the Stack, and pointed it at the same address on the managed heap as that referenced by p1 (when you made the assignement p2 = p1).
在这种情况下,您已经在托管堆上创建了person类的一个新实例,它的指针p1位于引用该对象的堆栈上,并再次将对象实例的名称属性指定为“Jim Morrison”。接下来,您在堆栈中创建了另一个指针p2,并将它指向托管堆上与p1引用的地址相同的地址(当您创建assignement p2 = p1时)。
Here comes the twist. When you the Assign the Name property of p2 the value "Janis Joplin" you are changing the Name property for the object REFERENCED by Both p1 and p2, such that, if you ran the following code:
转折来了。当您为p2分配名称属性值“Janis Joplin”时,您正在更改p1和p2引用的对象的名称属性,这样,如果您运行以下代码:
MsgBox(P1.Name)
'Will return "Janis Joplin"
MsgBox(p2.Name)
'will ALSO return "Janis Joplin"Because both variables (Pointers on the Stack) reference the SAME OBJECT in memory (an Address on the Managed Heap).
Did that make sense?
这样做有意义吗?
Last. If you do THIS:
最后一次。如果你这样做:
DIm p1 As New clsPerson
Dim p2 As New clsPerson
p1.Name = "Jim Morrison"
p2.Name = "Janis Joplin"
You now have two distinct Person Objects. However, the minute you do THIS again:
你现在有两个不同的人对象。然而,当你再次这样做的时候:
p2 = p1
You have now pointed both back to "Jim Morrison". (I am not exactly sure what happened to the Object on the Heap referenced by p2 . . . I THINK it has now gone out of scope. This is one of those areas where hopefullly someone can set me straight . . .). -EDIT: I BELIEVE this is why you would Set p2 = Nothing OR p2 = New clsPerson before making the new assignment.
你现在把这两者都指向了“吉姆·莫里森”。(我不确定p2所引用的堆上的对象发生了什么事)。我认为现在已经超出了范围。这是一个有希望的人能让我明白的领域之一。-编辑:我相信这就是为什么在做新的作业之前,你要设置p2 = Nothing或者p2 = New clsPerson。
Once again, if you now do THIS:
再一次,如果你现在这样做:
p2.Name = "Jimi Hendrix"
MsgBox(p1.Name)
MsgBox(p2.Name)
Both msgBoxes will now return "Jimi Hendrix"
两个msgbox现在将返回“吉米·亨德里克斯”
This can be pretty confusing for a bit, and I will say one last time, I may have some of the details wrong.
这可能会让人有点困惑,我最后再说一次,我可能有些细节弄错了。
Good Luck, and hopefully others who know better than me will come along to help clarify some of this . . .
祝你好运,希望那些比我更了解的人也能来帮助澄清其中的一些……
#5
3
value data type and reference data type
值数据类型和引用数据类型。
1) value( contain the data directly ) but reference ( refers to the data )
1)值(直接包含数据),但引用(引用数据)
2) in value( every variable has its own copy) but
in reference (more than variable can refer to some objects)
2) in value(每个变量都有自己的拷贝)但是in reference (more than variable can refer to some objects)
3) in value (operation variable can`t effect on other variable ) but in reference (variable can affect other )
3) in value(操作变量不能影响其他变量),in reference(变量可以影响其他变量)
4) value types are(int, bool, float) but reference type are (array , class objects , string )
4)值类型是(int, bool, float),但引用类型是(数组、类对象、字符串)
#6
1
"Variables that are based on value types directly contain values. Assigning one value type variable to another copies the contained value. This differs from the assignment of reference type variables, which copies a reference to the object but not the object itself." from Microsoft's library.
基于值类型的变量直接包含值。将一个值类型变量分配给另一个值类型变量将包含的值复制。这与引用类型变量的赋值不同,引用类型变量将引用复制到对象,而不是对象本身。
You can find a more complete answer here and here.
你可以在这里和这里找到一个更完整的答案。
#7
1
Sometimes explanations won't help especially for the beginners. You can imagine value type as data file and reference type as a shortcut to a file.
有时候,解释对初学者没有帮助。可以将值类型想像为数据文件和引用类型作为文件的快捷方式。
So if you copy a reference variable you only copy the link/pointer to a real data somewhere in memory. If you copy a value type, you really clone the data in memory.
因此,如果你复制一个引用变量,你只复制链接/指针到内存中的某个地方的真实数据。如果复制一个值类型,那么实际上是在内存中克隆数据。
#8
0
This is probably wrong in esoterical ways, but, to make it simple:
这可能在深奥的方面是错误的,但是,简单地说:
Value types are values that are passed normally "by value" (so copying them). Reference types are passed "by reference" (so giving a pointer to the original value). There isn't any guarantee by the .NET ECMA standard of where these "things" are saved. You could build an implementation of .NET that is stackless, or one that is heapless (the second would be very complex, but you probably could, using fibers and many stacks)
值类型是通常“按值”传递的值(因此复制它们)。引用类型是通过“引用”传递的(因此提供一个指向原始值的指针)。没有任何。net ECMA标准保证这些“东西”被保存在哪里。你可以构建一个。net实现,它是无堆叠的,或者是无堆的(第二个会非常复杂,但是你可能可以使用纤程和许多栈)
Structs are value type (int, bool... are structs, or at least are simulated as...), classes are reference type.
结构是值类型(int, bool…)是结构体,或者至少被模拟为…),类是引用类型。
Value types descend from System.ValueType. Reference type descend from System.Object.
值类型源自System.ValueType。引用类型源自System.Object。
Now.. In the end you have Value Type, "referenced objects" and references (in C++ they would be called pointers to objects. In .NET they are opaque. We don't know what they are. From our point of view they are "handles" to the object). These lasts are similar to Value Types (they are passed by copy). So an object is composed by the object (a reference type) and zero or more references to it (that are similar to value types). When there are zero references the GC will probably collect it.
现在. .最后,您有了值类型、“引用对象”和引用(在c++中,它们将被称为指向对象的指针)。在。net中,它们是不透明的。我们不知道它们是什么。在我们看来,它们是对象的“句柄”)。这些持续时间类似于值类型(它们是通过复制传递的)。因此,对象是由对象(引用类型)和对它的零个或多个引用(类似于值类型)组成的。当没有引用时,GC可能会收集它。
In general (in the "default" implementation of .NET), Value type can go on the stack (if they are local fields) or on the heap (if they are fields of a class, if they are variables in an iterator function, if they are variables referenced by a closure, if they are variable in an async function (using the newer Async CTP)...). Referenced value can only go to the heap. References use the same rules as Value types.
(在“默认”实现的。net),值类型可以在堆栈上(如果他们是本地字段)或在堆上(如果他们是类的字段,如果他们在一个迭代器函数变量,如果变量引用的一个闭包,如果他们在一个异步函数变量(使用新的异步CTP)……)。引用的值只能到堆中。引用使用与值类型相同的规则。
In the cases of Value Type that go on the heap because they are in an iterator function, an async function, or are referenced by a closure, if you watch the compiled file you'll see that the compiler created a class to put these variables, and the class is built when you call the function.
值类型的情况下,堆上的,因为他们是在一个迭代器函数,一个异步函数,或者引用一个闭包,如果你观察你会发现编译器编译后的文件创建一个类来把这些变量,构建和类时调用的函数。
Now, I don't know how to write long things, and I have better things to do in my life. If you want a "precise" "academic" "correct" version, read THIS:
现在,我不知道怎么写长篇大论,我有更好的事情要做。如果你想要一个“精确的”“学术的”“正确的”版本,请阅读以下内容:
http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx
http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx
It's 15 minutes I'm looking for it! It's better than the msdn versions, because it's a condensed "ready to use" article.
我找了15分钟!它比msdn版本要好,因为它是一篇浓缩的“准备使用”文章。
#9
0
The simplest way to think of reference types is to consider them as being "object-IDs"; the only things one can do with an object ID are create one, copy one, inquire or manipulate the type of one, or compare two for equality. An attempt to do anything else with an object-ID will be regarded as shorthand for doing the indicated action with the object referred to by that id.
认为引用类型最简单的方法是将其视为“对象- id”;唯一可以用对象ID做的事情是创建一个、复制一个、查询或操作一个类型,或者比较两个以实现相等。尝试使用对象id执行任何其他操作将被视为使用该id引用的对象执行指示操作的简写。
Suppose I have two variables X and Y of type Car--a reference type. Y happens to hold "object ID #19531". If I say "X=Y", that will cause X to hold "object ID #19531". Note that neither X nor Y holds a car. The car, otherwise known as "object ID #19531", is stored elsewhere. When I copied Y into X, all I did was copy the ID number. Now suppose I say X.Color=Colors.Blue. Such a statement will be regarded as an instruction to go find "object ID#19531" and paint it blue. Note that even though X and Y now refer to a blue car rather than a yellow one, the statement doesn't actually affect X or Y, because both still refer to "object ID #19531", which is still the same car as it always has been.
假设我有两个变量X和Y类型的车——一个引用类型。Y恰好持有“对象ID #19531”。如果我说“X=Y”,会导致X保存“对象ID #19531”。注意,X和Y都不拥有汽车。这辆车,也被称为“object ID #19531”,被存放在其他地方。当我把Y复制到X时,我所做的就是复制ID号。现在假设我说x。color = colors。blue。这样的声明将被视为一种指示去寻找“object ID#19531”并将其涂成蓝色。请注意,尽管X和Y现在指的是一辆蓝色的汽车,而不是黄色的汽车,但这个语句实际上并不影响X或Y,因为这两个语句仍然指的是“object ID #19531”,它仍然和以前一样。
#10
0
Variable types and Reference Value are easy to apply and well applied to the domain model, facilitate the development process.
变量类型和引用值易于应用和很好地应用于域模型,便于开发过程。
To remove any myth around the amount of "value type", I will comment on how this is handled on the platform. NET, specifically in C # (CSharp) when called APIS and send parameters by value, by reference, in our methods, and functions and how to make the correct treatment of the passages of these values.
要消除关于“值类型”数量的任何误解,我将评论如何在平台上处理它。NET,特别是c# (CSharp),当调用api时,通过值、引用、方法和函数发送参数,以及如何正确处理这些值的段落。
Read this article Variable Type Value and Reference in C #
请阅读c#中的变量类型值和引用
#11
0
Suppose v
is a value-type expression/variable, and r
is a reference-type expression/variable
假设v是一个值类型表达式/变量,而r是一个引用类型表达式/变量。
x = v
update(v) //x will not change value. x stores the old value of v
x = r
update(r) //x now refers to the updated r. x only stored a link to r,
//and r can change but the link to it doesn't .
So, a value-type variable stores the actual value (5, or "h"). A reference-type varaible only stores a link to a metaphorical box where the value is.
因此,值类型变量存储实际值(5或“h”)。引用类型varaible只存储到具有该值的隐喻框的链接。
#12
0
Simply put, value types get passed by their value and reference types by their reference (memory address).
简单地说,值类型通过它们的值和引用类型(内存地址)传递。
This means that changes made to the value type parameters (the formal parameters) inside a called method will not reflect in the values from where the method was called (the actual parameters).
这意味着在一个被调用的方法中对值类型参数(形式参数)所做的更改不会反映在调用方法的值(实际参数)中。
But changes made to reference parameters inside a called method will reflect in changes to the variables declared in the calling method.
但是对被调用方法中的引用参数所做的更改将反映调用方法中声明的变量的更改。
That's a brief explanation. Refer to here to understand in detail about value types, reference types, and values type vs. reference type.
这是一个简短的解释。要详细了解值类型、引用类型和值类型与引用类型,请参阅这里。
#13
0
Value Type:
值类型:
-
Fixed memory size.
固定的内存大小。
-
Stored in Stack memory.
存储在栈内存中。
-
Holds actual value.
有实际价值。
Ex. int, char, bool, etc...
int, char, bool等…
Reference Type:
引用类型:
-
Not fixed memory.
不是固定的内存。
-
Stored in Heap memory.
存储在堆内存中。
-
Holds memory address of actual value.
保存实际值的内存地址。
Ex. string, array, class, etc...
字符串、数组、类等。
#14
0
There is not a single difference between value types and reference types, there are many little details that are stated explicitly by the standard and some of them are not easy to understand, especially for beginners.
在值类型和引用类型之间没有一个单独的区别,有许多小细节是由标准显式声明的,其中一些不容易理解,特别是对于初学者来说。
See ECMA standard 33, Common Language Infrastructure (CLI). The CLI is also standardized by the ISO. I would provide a reference but for ECMA we must download a PDF and that link depends on the version number. ISO standards cost money.
参见ECMA标准33,公共语言基础设施(CLI)。CLI也通过ISO进行标准化。我会提供一个参考,但是对于ECMA,我们必须下载PDF,这个链接取决于版本号。ISO标准成本钱。
One difference is that value types can be boxed but reference types generally cannot be. There are exceptions but they are quite technical.
一个区别是值类型可以被装箱,但是引用类型通常不能被装箱。有例外,但都是技术性的。
Value types cannot have parameter-less instance constructors or finalizers and they cannot refer to themselves. Referring to themselves means for example that if there is a value type Node then a member of Node cannot be a Node. I think there are other requirements/limitations in the specifications but if so then they are not gathered together in one place.
值类型不能有无参数的实例构造函数或终结器,也不能引用它们自己。引用本身意味着,例如,如果有一个值类型节点,那么节点的成员就不能是节点。我认为规范中还有其他的需求/限制,但是如果有,那么它们不会集中在一个地方。