.NET中的结构和类有什么区别?
当前回答
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类型。
其他回答
结构与等级
结构是一种值类型,因此它存储在堆栈上,但类是一种引用类型,存储在堆上。
结构不支持继承和多态,但类同时支持两者。
默认情况下,所有结构成员都是公共的,但类成员在本质上默认是私有的。
由于结构是一种值类型,我们不能将null赋给结构对象,但类的情况并非如此。
如前所述:类是引用类型,而结构是具有所有后果的值类型。
根据经验,框架设计指南建议在以下情况下使用结构而不是类:
它的实例大小小于16字节它逻辑上表示单个值,类似于原始类型(int、double等)它是不可变的它不必经常装箱
在.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.
类可以是空的-引用可以指向空。
结构是实际值-它们可以为空,但决不能为空。因此,结构总是有一个没有参数的默认构造函数——它们需要一个“起始值”。
从微软在类和结构之间的选择。。。
根据经验,框架中的大多数类型应该是类。然而,在某些情况下值类型的特性使其更适合使用结构。✓ 考虑结构而不是类:如果该类型的实例很小并且通常很短,或者通常嵌入在其他对象中。X避免结构,除非该类型具有以下所有属性特点:它在逻辑上表示单个值,类似于原始类型(int、double等)。它的实例大小小于16字节。它是不可变的。(无法更改)它不必经常装箱。
除了访问说明符的基本区别,以及上面提到的几个区别之外,我还想添加一些主要区别,包括上面提到的一些区别,以及带有输出的代码示例,这将提供对引用和值的更清晰的了解
结构:
是值类型,不需要堆分配。内存分配不同,存储在堆栈中适用于小型数据结构影响性能,当我们将值传递给方法时,我们会传递整个数据结构,所有数据都传递给堆栈。构造函数只返回结构值本身(通常在堆栈上的临时位置),然后根据需要复制该值每个变量都有自己的数据副本,其中一个变量的操作不可能影响另一个变量。不支持用户指定的继承,它们隐式继承自类型对象
类别:
参考类型值存储在堆中存储对动态分配对象的引用构造函数是用new运算符调用的,但它不会在堆上分配内存多个变量可以引用同一对象对一个变量的操作可能会影响另一个变量引用的对象
代码示例
static void Main(string[] args)
{
//Struct
myStruct objStruct = new myStruct();
objStruct.x = 10;
Console.WriteLine("Initial value of Struct Object is: " + objStruct.x);
Console.WriteLine();
methodStruct(objStruct);
Console.WriteLine();
Console.WriteLine("After Method call value of Struct Object is: " + objStruct.x);
Console.WriteLine();
//Class
myClass objClass = new myClass(10);
Console.WriteLine("Initial value of Class Object is: " + objClass.x);
Console.WriteLine();
methodClass(objClass);
Console.WriteLine();
Console.WriteLine("After Method call value of Class Object is: " + objClass.x);
Console.Read();
}
static void methodStruct(myStruct newStruct)
{
newStruct.x = 20;
Console.WriteLine("Inside Struct Method");
Console.WriteLine("Inside Method value of Struct Object is: " + newStruct.x);
}
static void methodClass(myClass newClass)
{
newClass.x = 20;
Console.WriteLine("Inside Class Method");
Console.WriteLine("Inside Method value of Class Object is: " + newClass.x);
}
public struct myStruct
{
public int x;
public myStruct(int xCons)
{
this.x = xCons;
}
}
public class myClass
{
public int x;
public myClass(int xCons)
{
this.x = xCons;
}
}
输出
Struct Object的初始值为:10
内部结构方法Struct对象的内部方法值为:20
结构对象的方法调用值为:10
类对象的初始值为:10
内部类方法类对象的内部方法值为:20
类对象的方法调用值为:20
在这里,您可以清楚地看到按值调用和按引用调用之间的区别。
推荐文章
- 防止在ASP中缓存。NET MVC中使用属性的特定操作
- 转换为值类型'Int32'失败,因为物化值为空
- 接口方法的最终参数-有什么意义?
- c#中有任何连接字符串解析器吗?
- MSBuild路径
- c#和Java的主要区别是什么?
- 在c#中创建一个特定时区的DateTime
- .NET中的属性是什么?
- 如何使用try catch进行异常处理是最佳实践
- .NET中字节的字面后缀?
- 如何处理AccessViolationException
- c#忽略证书错误?
- 如何在Visual Studio中找到堆栈跟踪?
- 如何强制LINQ Sum()返回0而源集合是空的
- 什么时候使用Struct vs. OpenStruct?