.NET 中的 struct 和 class 有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13049/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What's the difference between struct and class in .NET?
提问by Keith
What's the difference between struct and class in .NET?
.NET 中的 struct 和 class 有什么区别?
回答by Lasse V. Karlsen
In .NET, there are two categories of types, reference typesand value types.
在 .NET 中,有两类类型,引用类型和值类型。
Structs are value typesand classes are reference types.
结构是值类型,类是引用类型。
The general difference is that a reference typelives on the heap, and a value typelives inline, that is, wherever it is your variable or field is defined.
一般的区别是引用类型存在于堆中,而值类型存在于内联中,也就是说,无论您在哪里定义变量或字段。
A variable containing a value typecontains the entire value typevalue. For a struct, that means that the variable contains the entire struct, with all its fields.
包含值类型的变量包含整个值类型值。对于结构体,这意味着变量包含整个结构体及其所有字段。
A variable containing a reference typecontains a pointer, or a referenceto somewhere else in memory where the actual value resides.
包含引用类型的变量包含一个指针,或对实际值所在的内存中其他位置的引用。
This has one benefit, to begin with:
这有一个好处,首先是:
- value typesalways contains a value
- reference typescan contain a null-reference, meaning that they don't refer to anything at all at the moment
- 值类型总是包含一个值
- 引用类型可以包含空引用,这意味着它们目前根本不引用任何内容
Internally, reference types are implemented as pointers, and knowing that, and knowing how variable assignment works, there are other behavioral patterns:
在内部,引用类型被实现为指针,知道这一点,并且知道变量赋值是如何工作的,还有其他行为模式:
- copying the contents of a value typevariable into another variable, copies the entire contents into the new variable, making the two distinct. In other words, after the copy, changes to one won't affect the other
- copying the contents of a reference typevariable into another variable, copies the reference, which means you now have two references to the same somewhere elsestorage of the actual data. In other words, after the copy, changing the data in one reference will appear to affect the other as well, but only because you're really just looking at the same data both places
- 将值类型变量的内容复制到另一个变量中,将整个内容复制到新变量中,使两者不同。换句话说,复制后,对一个的更改不会影响另一个
- 将引用类型变量的内容复制到另一个变量中,复制引用,这意味着您现在有两个引用到相同的其他地方存储实际数据。换句话说,在复制之后,更改一个引用中的数据似乎也会影响另一个引用,但这只是因为您实际上只是在两个地方查看相同的数据
When you declare variables or fields, here's how the two types differ:
当您声明变量或字段时,这两种类型的区别如下:
- variable: value typelives on the stack, reference typelives on the stack as a pointer to somewhere in heap memory where the actual memory lives (though note Eric Lipperts article series: The Stack Is An Implementation Detail.)
- class/struct-field: value typelives completely inside the type, reference typelives inside the type as a pointer to somewhere in heap memory where the actual memory lives.
- 变量:值类型存在于堆栈中,引用类型作为指向实际内存所在的堆内存中某处的指针存在于堆栈中(但请注意Eric Lipperts 文章系列:堆栈是一个实现细节。)
- 类/结构字段:值类型完全位于类型内部,引用类型位于类型内部,作为指向实际内存所在的堆内存中某处的指针。
回答by Thomas Bratt
A short summary of each:
每个的简短摘要:
Classes Only:
仅限课程:
- Can support inheritance
- Are reference (pointer) types
- The reference can be null
- Have memory overhead per new instance
- 可以支持继承
- 是引用(指针)类型
- 引用可以为空
- 每个新实例的内存开销
Structs Only:
仅结构:
- Cannot support inheritance
- Are value types
- Are passed by value (like integers)
- Cannot have a null reference (unless Nullable is used)
- Do not have a memory overhead per new instance - unless 'boxed'
- 不能支持继承
- 是值类型
- 按值传递(如整数)
- 不能有空引用(除非使用 Nullable)
- 每个新实例没有内存开销 - 除非“装箱”
Both Classes and Structs:
类和结构体:
- Are compound data types typically used to contain a few variables that have some logical relationship
- Can contain methods and events
- Can support interfaces
- 复合数据类型通常用于包含一些具有某种逻辑关系的变量吗
- 可以包含方法和事件
- 可以支持接口
回答by Keith
In .NET the struct and class declarations differentiate between reference types and value types.
在 .NET 中,结构和类声明区分引用类型和值类型。
When you pass round a reference type there is only one actually stored. All the code that accesses the instance is accessing the same one.
当你传递一个引用类型时,实际上只存储了一个。所有访问实例的代码都在访问同一个。
When you pass round a value type each one is a copy. All the code is working on its own copy.
当您传递一个值类型时,每个值类型都是一个副本。所有代码都在自己的副本上工作。
This can be shown with an example:
这可以用一个例子来说明:
struct MyStruct
{
string MyProperty { get; set; }
}
void ChangeMyStruct(MyStruct input)
{
input.MyProperty = "new value";
}
...
// Create value type
MyStruct testStruct = new MyStruct { MyProperty = "initial value" };
ChangeMyStruct(testStruct);
// Value of testStruct.MyProperty is still "initial value"
// - the method changed a new copy of the structure.
For a class this would be different
对于一个类,这将是不同的
class MyClass
{
string MyProperty { get; set; }
}
void ChangeMyClass(MyClass input)
{
input.MyProperty = "new value";
}
...
// Create reference type
MyClass testClass = new MyClass { MyProperty = "initial value" };
ChangeMyClass(testClass);
// Value of testClass.MyProperty is now "new value"
// - the method changed the instance passed.
Classes can be nothing - the reference can point to a null.
类可以什么都不是——引用可以指向一个空值。
Structs are the actual value - they can be empty but never null. For this reason structs always have a default constructor with no parameters - they need a 'starting value'.
结构是实际值——它们可以为空,但绝不为空。出于这个原因,结构体总是有一个没有参数的默认构造函数——它们需要一个“起始值”。
回答by shana
Difference between Structs and Classes:
结构体和类的区别:
- Structs are value typewhereas Classes are reference type.
- Structs are stored on the stackwhereas Classes are stored on the heap.
- Value types hold their value in memory where they are declared, but reference type holds a reference to an object memory.
- Value types destroyed immediatelyafter the scope is lost whereas reference type only the variable destroy after the scope is lost. The object is later destroyed by the garbage collector.
- When you copy struct into another struct, a new copy of that struct gets created modified of one struct won't affect the value of the other struct.
- When you copy a class into another class, it only copies the reference variable.
- Both the reference variable point to the same object on the heap. Change to one variable will affect the other reference variable.
- Structs can not have destructors, but classes can have destructors.
- Structs can not have explicit parameterless constructorswhereas a class can structs doesn't support inheritance, but classes do. Both support inheritance from an interface.
- Structs are sealed type.
- 结构是值类型,而类是引用类型。
- 结构存储在堆栈上,而类存储在堆上。
- 值类型在声明它们的内存中保存它们的值,但引用类型保存对对象内存的引用。
- 范围丢失后立即销毁值类型,而引用类型仅在范围丢失后销毁变量。该对象稍后被垃圾收集器销毁。
- 当您将结构复制到另一个结构中时,会创建该结构的新副本,修改一个结构不会影响另一个结构的值。
- 当您将一个类复制到另一个类时,它只会复制引用变量。
- 两个引用变量都指向堆上的同一个对象。更改一个变量会影响另一个参考变量。
- 结构不能有析构函数,但类可以有析构函数。
- 结构不能有显式的无参数构造函数,而类可以结构不支持继承,但类支持。两者都支持从接口继承。
- 结构是密封型的。
回答by Sunsetquest
From Microsoft's Choosing Between Class and Struct...
As a rule of thumb, the majority of types in a framework should be classes. There are, however, some situations in which the characteristics of a value type make it more appropriate to use structs.
?CONSIDER a structinstead of a class:
- If instances of the type are small and commonly short-lived or are commonly embedded in other objects.
XAVOID a structunless the type has allof the following characteristics:
- It logically represents a single value, similar to primitive types (int, double, etc.).
- It has an instance size under 16 bytes.
- It is immutable. (cannot be changed)
- It will not have to be boxed frequently.
根据经验,框架中的大多数类型应该是类。然而,在某些情况下,值类型的特性使其更适合使用结构体。
? 考虑一个结构而不是一个类:
- 如果该类型的实例很小且通常寿命很短,或者通常嵌入其他对象中。
X避免使用结构,除非该类型具有以下所有特征:
- 它在逻辑上表示单个值,类似于原始类型(int、double 等)。
- 它的实例大小低于 16 字节。
- 它是不可变的。(无法更改)
- 它不必经常装箱。
回答by Venkat
In addition to all differences described in the other answers:
除了其他答案中描述的所有差异之外:
- Structs cannot have an explicit parameterless constructorwhereas a class can
- Structs cannot have destructors, whereas a class can
- Structs can't inheritfrom another struct or class whereas a class can inherit from another class. (Both structs and classes can implement from an interface.)
- 结构不能有显式的无参数构造函数,而类可以
- 结构不能有析构函数,而类可以
- 结构不能从另一个结构或类继承,而一个类可以从另一个类继承。(结构和类都可以从接口实现。)
If you are after a video explaining all the differences, you can check out Part 29 - C# Tutorial - Difference between classes and structs in C#.
如果您正在观看解释所有差异的视频,您可以查看第 29 部分 - C# 教程 - C# 中的类和结构之间的差异。
回答by Zooba
Instances of classes are stored on the managed heap. All variables 'containing' an instance are simply a reference to the instance on the heap. Passing an object to a method results in a copy of the reference being passed, not the object itself.
类的实例存储在托管堆上。所有“包含”实例的变量只是对堆上实例的引用。将对象传递给方法会导致传递引用的副本,而不是对象本身。
Structures (technically, value types) are stored wherever they are used, much like a primitive type. The contents may be copied by the runtime at any time and without invoking a customised copy-constructor. Passing a value type to a method involves copying the entire value, again without invoking any customisable code.
结构(从技术上讲,值类型)存储在它们使用的任何地方,很像原始类型。运行时可以随时复制内容,而无需调用定制的复制构造函数。将值类型传递给方法涉及复制整个值,同样无需调用任何可自定义的代码。
The distinction is made better by the C++/CLI names: "ref class" is a class as described first, "value class" is a class as described second. The keywords "class" and "struct" as used by C# are simply something that must be learned.
C++/CLI 名称可以更好地区分:“ref class”是第一个描述的类,“value class”是第二个描述的类。C# 中使用的关键字“class”和“struct”只是必须学习的东西。
回答by 0xaryan
+------------------------+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+
| | Struct | Class |
+------------------------+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+
| Type | Value-type | Reference-type |
| Where | On stack / Inline in containing type | On Heap |
| Deallocation | Stack unwinds / containing type gets deallocated | Garbage Collected |
| Arrays | Inline, elements are the actual instances of the value type | Out of line, elements are just references to instances of the reference type residing on the heap |
| Aldel Cost | Cheap allocation-deallocation | Expensive allocation-deallocation |
| Memory usage | Boxed when cast to a reference type or one of the interfaces they implement, | No boxing-unboxing |
| | Unboxed when cast back to value type | |
| | (Negative impact because boxes are objects that are allocated on the heap and are garbage-collected) | |
| Assignments | Copy entire data | Copy the reference |
| Change to an instance | Does not affect any of its copies | Affect all references pointing to the instance |
| Mutability | Should be immutable | Mutable |
| Population | In some situations | Majority of types in a framework should be classes |
| Lifetime | Short-lived | Long-lived |
| Destructor | Cannot have | Can have |
| Inheritance | Only from an interface | Full support |
| Polymorphism | No | Yes |
| Sealed | Yes | When have sealed keyword |
| Constructor | Can not have explicit parameterless constructors | Any constructor |
| Null-assignments | When marked with nullable question mark | Yes (+ When marked with nullable question mark in C# 8+) |
| Abstract | No | When have abstract keyword |
| Member Access Modifiers| public, private, internal | public, protected, internal, protected internal, private protected |
+------------------------+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+
回答by Will Calderwood
To add to the other answers, there is one fundamental difference that is worth noting, and that is how the data is stored within arrays as this can have a major effect on performance.
要添加到其他答案中,有一个值得注意的根本区别,那就是数据如何存储在数组中,因为这会对性能产生重大影响。
- With a struct, the array contains the instance of the struct
- With a class, the array contains a pointer to an instance of the class elsewhere in memory
- 对于结构体,数组包含结构体的实例
- 对于一个类,该数组包含一个指向该类在内存中其他地方的实例的指针
So an array of structs looks like this in memory
所以一个结构数组在内存中看起来像这样
[struct][struct][struct][struct][struct][struct][struct][struct]
[struct][struct][struct][struct][struct][struct][struct][struct]
Whereas an array of classes looks like this
而一系列类看起来像这样
[pointer][pointer][pointer][pointer][pointer][pointer][pointer][pointer]
[pointer][pointer][pointer][pointer][pointer][pointer][pointer][pointer]
With an array of classes, the values you're interested in are not stored within the array, but elsewhere in memory.
对于类数组,您感兴趣的值不会存储在数组中,而是存储在内存中的其他地方。
For a vast majority of applications this difference doesn't really matter, however, in high performance code this will affect locality of data within memory and have a large impact on the performance of the CPU cache. Using classes when you could/should have used structs will massively increase the number of cache misses on the CPU.
对于绝大多数应用程序,这种差异并不重要,但是,在高性能代码中,这将影响内存中数据的局部性,并对 CPU 缓存的性能产生很大影响。当您可以/应该使用结构体时使用类将大大增加 CPU 上的缓存未命中数。
The slowest thing a modern CPU does is not crunching numbers, it's fetching data from memory, and an L1 cache hit is many times faster than reading data from RAM.
现代 CPU 所做的最慢的事情不是处理数字,而是从内存中获取数据,并且 L1 缓存命中比从 RAM 读取数据快很多倍。
Here's some code you can test. On my machine, iterating through the class array takes ~3x longer than the struct array.
这是您可以测试的一些代码。在我的机器上,遍历类数组需要比结构数组长约 3 倍的时间。
private struct PerformanceStruct
{
public int i1;
public int i2;
}
private class PerformanceClass
{
public int i1;
public int i2;
}
private static void DoTest()
{
var structArray = new PerformanceStruct[100000000];
var classArray = new PerformanceClass[structArray.Length];
for (var i = 0; i < structArray.Length; i++)
{
structArray[i] = new PerformanceStruct();
classArray[i] = new PerformanceClass();
}
long total = 0;
var sw = new Stopwatch();
sw.Start();
for (var loops = 0; loops < 100; loops++)
for (var i = 0; i < structArray.Length; i++)
{
total += structArray[i].i1 + structArray[i].i2;
}
sw.Stop();
Console.WriteLine($"Struct Time: {sw.ElapsedMilliseconds}");
sw = new Stopwatch();
sw.Start();
for (var loops = 0; loops < 100; loops++)
for (var i = 0; i < classArray.Length; i++)
{
total += classArray[i].i1 + classArray[i].i2;
}
Console.WriteLine($"Class Time: {sw.ElapsedMilliseconds}");
}
回答by Swagatika dhal
Structure vs Class
结构与类
A structure is a value type so it is stored on the stack, but a class is a reference type and is stored on the heap.
结构是值类型,因此存储在堆栈中,而类是引用类型,存储在堆中。
A structure doesn't support inheritance, and polymorphism, but a class supports both.
结构不支持继承和多态,但类同时支持两者。
By default, all the struct members are public but class members are by default private in nature.
默认情况下,所有结构成员都是公共的,但类成员本质上是私有的。
As a structure is a value type, we can't assign null to a struct object, but it is not the case for a class.
由于结构是值类型,我们不能将 null 分配给结构对象,但对于类则不是这种情况。

