当前位置:  开发笔记 > 编程语言 > 正文

.NET中struct和class之间有什么区别?

如何解决《.NET中struct和class之间有什么区别?》经验,为你挑选了12个好方法。

.NET中struct和class之间有什么区别?



1> angry person..:

在.NET中,有两类类型,引用类型值类型.

结构是值类型,类是引用类型.

一般的区别是引用类型存在于堆上,并且值类型保持内联,即,无论何处定义了变量或字段.

包含值类型的变量包含整个值类型值.对于结构,这意味着变量包含整个结构及其所有字段.

包含引用类型的变量包含指针或对实际值所在的内存中其他位置的引用.

这有一个好处,首先:

值类型始终包含值

引用类型可以包含引用,这意味着它们目前根本不引用任何内容

在内部,引用类型被实现为指针,并且知道并且知道变量赋值如何工作,还有其他行为模式:

值类型变量的内容复制到另一个变量中,将整个内容复制到新变量中,使两者不同.换句话说,在复制之后,对一个的更改不会影响另一个

引用类型变量的内容复制到另一个变量中,复制引用,这意味着您现在有两个对实际数据的其他位置存储的引用.换句话说,在复制之后,更改一个引用中的数据也会影响另一个引用,但这只是因为你真的只是在同一个数据中查看两个地方

声明变量或字段时,这两种类型的区别如下:

变量:值类型存在于堆栈中,引用类型作为指向堆内存中某个地方的指针存在于实际内存中(尽管请注意Eric Lipperts文章系列:堆栈是实现细节.)

class/struct-field:value类型完全位于类型内部,引用类型位于类型内部,作为指向实际内存所在的堆内存中某处的指针.


为了完全完整,我应该提到Eric Lippert已经说过[堆栈是一个实现细节](http://blogs.msdn.com/b/ericlippert/archive/2009/04/27/the-stack -is-an-implementation-detail.aspx),每当我提到上面的堆栈时,请记住Eric的帖子.
另一个关键的区别是用法.来自MSDN:"结构通常用于封装一小组相关变量,例如矩形的坐标.结构也可以包含构造函数,常量,字段,方法,属性,索引器,运算符,事件和嵌套类型,尽管如此几个成员是必需的,你应该考虑让你的类型成为一个类."
C++结构和类中的@KorayTugay绝对等效,除了一件事 - 默认访问限制(类默认为private,struct为public)
@KorayTugay不,不是。
这对C ++也有效吗?

2> Thomas Bratt..:

每个简短摘要:

仅限课程:

可以支持继承

是引用(指针)类型

引用可以为null

每个新实例都有内存开销

仅限结构:

不能支持继承

是价值类型

按值传递(如整数)

不能有空引用(除非使用Nullable)

每个新实例都没有内存开销 - 除非'盒装'

类和结构:

复合数据类型通常用于包含一些具有某种逻辑关系的变量

可以包含方法和事件

可以支持接口


这个答案的某些部分并不完全正确.类并不总是在堆上,并且结构不总是在堆栈上.当前的异常包括类的结构字段,匿名方法和lambda表达式中捕获的变量,迭代器块以及已经提到的盒装值.但堆栈与堆分配是一个实现细节,可能会有所变化.[Eric lippart在此讨论](http://blogs.msdn.com/b/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx).我已经投票了,但如果你更新,我会很乐意删除它.
@MarkAmery我对你的表达式"没有内存开销"有同样的初始反应,但我认为OP指的是`class`的实例是托管内存(由垃圾收集器处理),而实例`struct`不是.
您可能想澄清当声明结构*“每个新实例没有内存开销” *时的含义。我的第一个解释是,您声称-显然是荒谬的-结构使用零内存。然后,我想也许您是想说一个结构,与类不同,它所需要的内存恰好等于其成员字段总和,而不再需要。但是后来我用Google搜索了“ c#struct memory memory”,并发现了Hans Passant的[this answer](http://stackoverflow.com/a/33672124/1709587),说不,也不是。所以你是什么意思?

3> Keith..:

在.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.

对于一个课程,这将是不同的

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.

类可以是空的 - 引用可以指向null.

结构是实际值 - 它们可以为空但从不为空.出于这个原因,结构总是有一个没有参数的默认构造函数 - 它们需要一个'起始值'.



4> 小智..:

结构和类之间的区别:

结构是值类型,类是引用类型.

结构存储在堆栈中,类存储在堆上.

值类型在声明它们的内存中保存它们的值,但引用类型包含对象内存的引用.

在范围丢失后立即销毁的值类型,而引用类型仅在范围丢失后销毁变量.该对象稍后被垃圾收集器破坏.

将struct复制到另一个struct时,会创建该struct的新副本,修改一个struct不会影响另一个struct的值.

将类复制到另一个类时,它只复制引用变量.

两个引用变量都指向堆上的同一个对象.更改为一个变量将影响另一个参考变量.

结构不能有析构函数,但类可以有析构函数.

结构不能有明确的无参数构造函数,而类结构可以不支持继承,但类可以.两者都支持从接口继承.

结构是密封型的.



5> Sunsetquest..:

来自微软在类和结构之间的选择 ......

根据经验,框架中的大多数类型应该是类.但是,在某些情况下,值类型的特征使得使用结构更合适.

考虑结构而不是类:

如果该类型的实例很小并且通常是短暂的或通常嵌入在其他对象中.

除非类型具有以下所有特征,否则X 避免使用结构:

它在逻辑上表示单个值,类似于原始类型(int,double等).

它的实例大小小于16个字节.

这是不可改变的.(不能改变)

它不必经常装箱.



6> 小智..:

除了其他答案中描述的所有差异:

    结构不能有明确的无参数构造函数,而类可以

    结构不能有析构函数,而类可以

    结构不能从另一个结构或类继承,而类可以从另一个类继承.(结构和类都可以从接口实现.)

如果您正在阅读解释所有差异的视频,您可以查看第29部分 - C#教程 - C#中的类和结构之间的差异.


比.net语言通常不允许结构定义无参数构造函数(是否允许它由语言编译器决定)这一事实更重要的是结构可以存在并暴露出来没有任何类型的构造函数被运行到外部世界(即使定义了无参数构造函数)..net语言通常禁止结构的无参数构造函数的原因是为了避免由于有时运行这种构造函数而有时不运行而导致的混淆.

7> Zooba..:

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

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

通过C++/CLI名称可以更好地区分:"ref class"是首先描述的类,"value class"是第二个描述的类.C#使用的关键字"class"和"struct"只是必须学习的东西.



8> 小智..:

结构与类

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

结构不支持继承和多态,但是类支持两者.

默认情况下,所有struct成员都是公共的,但类成员默认是私有的.

由于结构是值类型,因此我们不能将null分配给结构对象,但类不是这种情况.


关于"所有结构成员都是公开的":如果我没有弄错,那是不正确的."默认情况下,类成员和结构成员的访问级别(包括嵌套类和结构)是私有的." https://msdn.microsoft.com/en-us/library/ms173121.aspx

9> Will Calderw..:

除了其他答案外,还有一个基本区别值得注意,那就是它在内存中的存储方式。这会对阵列的性能产生重大影响。结构是值类型,因此它们将值存储在它们指向的内存区域中,类是引用类型,因此它们在它们指向的内存区域中引用一个类,实际值存储在其他位置。

通过结构,可以在包含类中分配内存以存储数据。

对于一个类,包含类将只在不同的内存区域中包含一个指向新类的指针。

数组也是如此,因此结构数组在内存中看起来像这样

[struct][struct][struct][struct][struct][struct][struct][struct]

作为一组类的数组看起来像这样

[pointer][pointer][pointer][pointer][pointer][pointer][pointer][pointer]

您感兴趣的实际值实际上并不存储在数组中,而是存储在内存中的其他位置。

对于绝大多数应用程序而言,这种区别并不重要,但是,在高性能代码中,这将影响内存中数据的局部性,并对CPU缓存的性能产生重大影响。在可以/应该使用结构的情况下使用类将大大增加CPU上的高速缓存未命中数。

现代CPU最慢的操作不是处理数字,而是从内存中获取数据,并且一级缓存命中率比从RAM中读取数据快许多倍。



10> 小智..:

为了使其完整,使用该Equals方法时存在另一个差异,该方法由所有类和结构继承.

让我们说我们有一个类和一个结构:

class A{
  public int a, b;
}
struct B{
  public int a, b;
}

在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;
}

然后:

s1.Equals(s2) // true
s1.Equals(c1) // false
c1.Equals(c2) // false
c1 == c2 // false

因此,结构适用于类似数字的对象,如点(保存x和y坐标).课程适合其他人.即使2个人有相同的名字,身高,体重......,他们仍然是2个人.



11> 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                                                                        |
| Access Modifiers      | public, private, internal                                                                            | public, protected, internal, protected internal, private protected                                |
+-----------------------+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+



12> Ed S...:

好吧,对于初学者来说,结构是通过值而不是通过引用传递的。结构适合于相对简单的数据结构,而从架构的角度来看,通过多态和继承,类具有更大的灵活性。

其他人可能会给您比我更多的细节,但是当我要使用的结构很简单时,我会使用结构。

推荐阅读
wurtjq
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有