.NET中的结构和类有什么区别?


当前回答

结构与等级

结构是一种值类型,因此它存储在堆栈上,但类是一种引用类型,存储在堆上。

结构不支持继承和多态,但类同时支持两者。

默认情况下,所有结构成员都是公共的,但类成员在本质上默认是私有的。

由于结构是一种值类型,我们不能将null赋给结构对象,但类的情况并非如此。

其他回答

类的实例存储在托管堆上。“包含”实例的所有变量都只是对堆上实例的引用。将对象传递给方法会导致传递引用的副本,而不是对象本身。

结构(从技术上讲,值类型)存储在使用它们的任何地方,很像原始类型。运行时可以随时复制内容,而无需调用自定义的复制构造函数。将值类型传递给方法涉及复制整个值,同样无需调用任何自定义代码。

C++/CLI名称使这种区别更加明显:“ref class”是第一个类,“value class”是第二个类。C#使用的关键字“class”和“struct”只是必须学习的东西。

在.NET中,结构和类声明区分引用类型和值类型。

传递引用类型时,实际存储的只有一个。访问实例的所有代码都在访问同一个实例。

传递值类型时,每个值类型都是副本。所有代码都在自己的副本上运行。

这可以用一个例子来说明:

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.

对于一个班级来说,这将是不同的

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.

类可以是空的-引用可以指向空。

结构是实际值-它们可以为空,但决不能为空。因此,结构总是有一个没有参数的默认构造函数——它们需要一个“起始值”。

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
Al-Del Cost Cheap allocation-deallocation Expensive allocation-deallocation
Memory usage Boxed when cast to a reference type or one of the interfaces they implement,
Unboxed when cast back to value type
(Negative impact because boxes are objects that are allocated on the heap and are garbage-collected)
No boxing-unboxing
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 (C#), or Sealed attribute (F#)
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+ and F# 5+ 1)
Abstract No When have abstract keyword (C#), or AbstractClass attribute (F#)
Member Access Modifiers public, private, internal public, protected, internal, protected internal, private protected

1不鼓励在F#中使用null,请改用Option类型。

我♥ 可视化,在这里我创建了一个来展示结构和类之间的基本区别。


以及文本表示,以防万一;)

+--------------------------------------------------+------+----------------------------------------------+
|                      Struct                      |      |                      Class                    |
+--------------------------------------------------+------+----------------------------------------------+
| - 1 per Thread.                                  |      | - 1 per application.                         |
|                                                  |      |                                              |
| - Holds value types.                             |      | - Holds reference types.                     |
|                                                  |      |                                              |
| - Types in the stack are positioned              |      | - No type ordering (data is fragmented).     |
|   using the LIFO principle.                      |      |                                              |
|                                                  |      |                                              |
| - Can't have a default constructor and/or        |      | - Can have a default constructor             |
|   finalizer(destructor).                         |      |   and/or finalizer.                          |
|                                                  |      |                                              |
| - Can be created with or without a new operator. |      | - Can be created only with a new operator.   |
|                                                  |      |                                              |
| - Can't derive from the class or struct          |  VS  | - Can have only one base class and/or        |
|   but can derive from the multiple interfaces.   |      |   derive from multiple interfaces.           |
|                                                  |      |                                              |
| - The data members can't be protected.           |      | - Data members can be protected.             |
|                                                  |      |                                              |
| - Function members can't be                      |      | - Function members can be                    |
|   virtual or abstract.                           |      |   virtual or abstract.                       |
|                                                  |      |                                              |
| - Can't have a null value.                       |      | - Can have a null value.                     |
|                                                  |      |                                              |
| - During an assignment, the contents are         |      | - Assignment is happening                    |
|   copied from one variable to another.           |      |   by reference.                              |
+--------------------------------------------------+------+----------------------------------------------+

有关更多信息,请查看以下内容:

类和结构(官方文档)。在类和结构之间选择(官方文档)。

每个项目的简短摘要:

仅限班级:

可以支持继承是引用(指针)类型引用不能为空每个新实例的内存开销

仅结构:

无法支持继承是值类型按值传递(如整数)不能有空引用(除非使用了Nullable)每个新实例没有内存开销-除非“装箱”

类和结构:

复合数据类型通常用于包含一些具有某种逻辑关系的变量吗可以包含方法和事件可以支持接口