Kei*_*ith 643 .net struct class value-type reference-type
.NET中struct和class之间有什么区别?
ang*_*son 1006
在.NET中,有两类类型,引用类型和值类型.
结构是值类型,类是引用类型.
一般的区别是引用类型存在于堆上,并且值类型保持内联,即,无论何处定义了变量或字段.
包含值类型的变量包含整个值类型值.对于结构,这意味着变量包含整个结构及其所有字段.
包含引用类型的变量包含指针或对实际值所在的内存中其他位置的引用.
这有一个好处,首先:
在内部,引用类型被实现为指针,并且知道并且知道变量赋值如何工作,还有其他行为模式:
声明变量或字段时,这两种类型的区别如下:
Tho*_*att 192
每个简短摘要:
仅限课程:
仅限结构:
类和结构:
Kei*_*ith 39
在.NET中,struct和class声明区分引用类型和值类型.
传递引用类型时,实际只存储了一个.访问该实例的所有代码都访问同一个代码.
传递值类型时,每个都是副本.所有代码都在自己的副本上工作.
这可以通过一个例子来展示:
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.
Run Code Online (Sandbox Code Playgroud)
对于一个课程,这将是不同的
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.
Run Code Online (Sandbox Code Playgroud)
类可以是空的 - 引用可以指向null.
结构是实际值 - 它们可以为空但从不为空.出于这个原因,结构总是有一个没有参数的默认构造函数 - 它们需要一个'起始值'.
小智 23
结构和类之间的区别:
小智 19
除了其他答案中描述的所有差异:
如果您正在阅读解释所有差异的视频,您可以查看第29部分 - C#教程 - C#中的类和结构之间的差异.
Ars*_*yan 17
一世 ?可视化,在这里我创建了一个来展示structs和classes之间的基本区别。
还有文字表示以防万一;)
+--------------------------------------------------+------+----------------------------------------------+
| Stack | | Heap |
+--------------------------------------------------+------+----------------------------------------------+
| - 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. |
+--------------------------------------------------+------+----------------------------------------------+
Run Code Online (Sandbox Code Playgroud)
有关更多信息,请查看以下内容:
Zoo*_*oba 15
类的实例存储在托管堆上.包含'实例的所有变量只是对堆上实例的引用.将对象传递给方法会导致传递的引用副本,而不是对象本身.
结构(技术上,值类型)存储在任何地方,就像原始类型一样.运行时可以随时复制内容,而无需调用自定义的复制构造函数.将值类型传递给方法涉及复制整个值,同样不需要调用任何可自定义的代码.
通过C++/CLI名称可以更好地区分:"ref class"是首先描述的类,"value class"是第二个描述的类.C#使用的关键字"class"和"struct"只是必须学习的东西.
小智 7
结构与类
结构是一种值类型,因此它存储在堆栈中,但类是引用类型并存储在堆上.
结构不支持继承和多态,但是类支持两者.
默认情况下,所有struct成员都是公共的,但类成员默认是私有的.
由于结构是值类型,因此我们不能将null分配给结构对象,但类不是这种情况.
除了其他答案外,还有一个基本区别值得注意,那就是它在内存中的存储方式。这会对阵列的性能产生重大影响。结构是值类型,因此它们将值存储在它们指向的内存区域中,类是引用类型,因此它们在它们指向的内存区域中引用一个类,实际值存储在其他位置。
数组也是如此,因此结构数组在内存中看起来像这样
[struct][struct][struct][struct][struct][struct][struct][struct]
作为一组类的数组看起来像这样
[pointer][pointer][pointer][pointer][pointer][pointer][pointer][pointer]
您感兴趣的实际值实际上并不存储在数组中,而是存储在内存中的其他位置。
对于绝大多数应用程序而言,这种区别并不重要,但是,在高性能代码中,这将影响内存中数据的局部性,并对CPU缓存的性能产生重大影响。在可以/应该使用结构的情况下使用类将大大增加CPU上的高速缓存未命中数。
现代CPU最慢的操作不是处理数字,而是从内存中获取数据,并且一级缓存命中率比从RAM中读取数据快许多倍。
为了使其完整,使用该Equals
方法时存在另一个差异,该方法由所有类和结构继承.
让我们说我们有一个类和一个结构:
class A{
public int a, b;
}
struct B{
public int a, b;
}
Run Code Online (Sandbox Code Playgroud)
在Main方法中,我们有4个对象.
static void Main{
A c1 = new A(), c2 = new A();
c1.a = c1.b = c2.a = c2.b = 1;
B s1 = new B(), s2 = new B();
s1.a = s1.b = s2.a = s2.b = 1;
}
Run Code Online (Sandbox Code Playgroud)
然后:
s1.Equals(s2) // true
s1.Equals(c1) // false
c1.Equals(c2) // false
c1 == c2 // false
Run Code Online (Sandbox Code Playgroud)
因此,结构适用于类似数字的对象,如点(保存x和y坐标).课程适合其他人.即使2个人有相同的名字,身高,体重......,他们仍然是2个人.
+-----------------------+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+
| | 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 |
| Access Modifiers | public, private, internal | public, protected, internal, protected internal, private protected |
+-----------------------+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+
Run Code Online (Sandbox Code Playgroud)
好吧,对于初学者来说,结构是通过值而不是通过引用传递的。结构适合于相对简单的数据结构,而从架构的角度来看,通过多态和继承,类具有更大的灵活性。
其他人可能会给您比我更多的细节,但是当我要使用的结构很简单时,我会使用结构。
在类中声明的事件通过 lock(this) 自动锁定其 += 和 -= 访问,以使其线程安全(静态事件锁定在类的类型上)。在结构中声明的事件不会自动锁定其 += 和 -= 访问。结构的 lock(this) 不起作用,因为您只能锁定引用类型表达式。
创建结构体实例不会导致垃圾回收(除非构造函数直接或间接创建引用类型实例),而创建引用类型实例会导致垃圾回收。
结构体总是有一个内置的公共默认构造函数。
class DefaultConstructor
{
static void Eg()
{
Direct yes = new Direct(); // Always compiles OK
InDirect maybe = new InDirect(); // Compiles if constructor exists and is accessible
//...
}
}
Run Code Online (Sandbox Code Playgroud)
这意味着结构始终是可实例化的,而类可能不是,因为它的所有构造函数都可能是私有的。
class NonInstantiable
{
private NonInstantiable() // OK
{
}
}
struct Direct
{
private Direct() // Compile-time error
{
}
}
Run Code Online (Sandbox Code Playgroud)结构不能有析构函数。析构函数只是伪装的 object.Finalize 的覆盖,作为值类型的结构不受垃圾回收的影响。
struct Direct
{
~Direct() {} // Compile-time error
}
class InDirect
{
~InDirect() {} // Compiles OK
}
And the CIL for ~Indirect() looks like this:
.method family hidebysig virtual instance void
Finalize() cil managed
{
// ...
} // end of method Indirect::Finalize
Run Code Online (Sandbox Code Playgroud)结构是隐式密封的,类不是。
结构不能是抽象的,类可以。
结构不能在其构造函数中调用 :base() 而没有显式基类的类可以。
一个结构不能扩展另一个类,一个类可以。
结构不能声明类可以的受保护成员(例如,字段、嵌套类型)。
结构不能声明抽象函数成员,抽象类可以。
结构不能声明虚函数成员,类可以。
结构不能声明密封的函数成员,类可以。
结构不能声明覆盖函数成员,类可以。
此规则的一个例外是结构可以覆盖 System.Object 的虚拟方法,即 Equals()、GetHashCode() 和 ToString()。
小智 5
如前所述:类是引用类型,而结构是具有所有后果的值类型。
根据规则框架设计指南建议在以下情况下使用结构而不是类:
归档时间: |
|
查看次数: |
327411 次 |
最近记录: |