c#中Class和Struct使用与性能的区别

Posted wolf96

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c#中Class和Struct使用与性能的区别相关的知识,希望对你有一定的参考价值。

在Unity中很多已经定义为结构体的数据结构
  • Vector2, Vector3 和 Vector4
  • Rect
  • Color和Color32
  • Bounds
  • Touch

1.Class为引用类型,Struct为值类型

值类型与引用类型的区别这两篇文章讲得很好 http://www.cnblogs.com/tonney/archive/2011/04/28/2032205.html
http://blog.csdn.net/liulong1567/article/details/50678930 虽然我们在.net中的框架类库中,大多是引用类型,但是我们程序员用得最多的还是值类型。

  引用类型如:string,Object,class等总是在从托管堆上分配的,C#中new操作符返回对象的内存地址--也就是指向对象数据的内存地址。


  以下是值类型与引用类型的表:        从这张图可以看出,class(类)实例化出来的对象,指向了内存堆中分配的空间                           struct(结构) 实例化出来的对象 ,是在 内存栈 中分配
   所以,值类型和引用类型的区别就是:             1、它们存储的位置不一样             2、如果是引用类型,当两个对象指向同一个地方,修改某一个的时候,其它对象的值会发生改变 当说到类的实例是传引用时,实际过程是,先获取一个指针,它指向对象在内存中的地址,然后传递这个指针。这很重要,因为一个类的实例,实际上可能很大,包含了很多域甚至其他对象。在这种情况下,赋值和传递整个实例可能非常影响性能,这就为什么要用传地址来替代。 说到传值时,实际过程是,对这个变量进行全克隆/拷贝,然后传递这个副本,原始值不变。结构体就是值类型,它是传值的。这意味着,结构体是理想的小型数据结构。
由于引用类型在托管堆上分配,它只会在调用垃圾回收时才被清理。 值类型实在内存栈上分配,这就说明他们很容易被回收,而且不受垃圾回收的影响。
数据类型分隔为值类型和引用类型。值类型要么是堆栈分配的,要么是在结构中以内联方式分配的。引用类型是堆分配的。引用类型和值类型都是从最终的基类 Object 派生出来的。当值类型需要充当对象时,就在堆上分配一个包装(该包装能使值类型看上去像引用对象一样),并且将该值类型的值复制给它。该包装被加上标记,以便系统知道它包含一个值类型。这个进程称为装箱,其反向进程称为取消装箱。装箱和取消装箱能够使任何类型像对象一样进行处理。

2.Class可以继承父类,Struct不可以

所有结构体都默认继承System.ValueType父类,所以不能继承别的父类,ValueType是值类型的基类,详见: https://msdn.microsoft.com/zh-cn/library/system.valuetype(VS.80).aspx


3.Struct必须在构造函数对所有变量赋值

结构体中所有变量都必须在构造函数中初始化

4.Struct没有默认构造函数


Struct不允许有参数为空的构造函数

5.Struct与class的性能上的优缺点

关于值类型与引用类型的内存可以看这篇文章: https://msdn.microsoft.com/zh-cn/dd365372
值类型的实例化之后在内存的大小就是其所有内容物大小,也就是内容物内存越大、占用内存越大,存放在栈中,但是取值更快,不需要GC回收 引用类型把值存放在堆中,引用存在栈中,实例化时要在堆中取值,所以更消耗时间,但是更省内存,因为只用引用指针的大小,需要GC回收

 值类型引用类型
内存
耗时
GC
   
   


6.Struct类型变量默认不可为空

也就是说,不能写这个语句 struct != null,如果像这样做的话,一定要加上?,为它取值要加上Value,判断是否为空要用HasValue Struct? struct = *****; if(struct.HasValue)      struct.Value.***** = ****; 原因参考这篇文章: http://blog.csdn.net/xiaojie_cp/article/details/45892325 值类型后面加问号表示可为空null(Nullable 结构) Nullable是.NET 2.0中新提供的一种用于标明一个值类型是否可以为空的技术。   对于一个类型,如果既可以给它分配一个值,也可以给它分配空引用null(表示没有任何值),我们就说这个类型是可空的。   因此,可空类型可表示一个值,或表示不存在任何值。例如,类似 String 的引用类型就是可空类型,而类似 Int32 的值类型不是可空类型。Nullable 结构支持将值类型扩展为可以为null,但不支持在引用类型上使用,因为引用类型本身就是可空的。 因为值类型的容量只够表示适合于该类型的值,因此它不可为空;值类型没有表示空值所需的额外容量。 例:public int? age;

等同 Nullable<int>


7.其他

值类型还有一个特性就是一旦修改值,就会产生一个值类型的副本 引用类型修改值,不会产生副本,但所有有该引用的值都会被修改

8.扩充

来自《深入理解C#》
值类型很能干,它们不需要垃圾回收,(除非被装箱)不会因类型标识而产生开销,也不需要解引用。
在其他方面,引用类型显得更能干,在传递参数、赋值、将值返回和执行类似的操作时,只需复制4或8字节(要看运行的是是32位还是64位CLR),而不是赋值全部数据。
值类型传给一个方法时,就得复制他的全部数据。
根据性能进行设计之前,需要衡量不同的选择。
类型(不管是类还是结构体),拥有多少方法并不重要,每个实例所占用的内存不会受到影响。(代码本身会消耗内存,但这只会发生一次,而不是每个实例都发生)
-update 2017/8/6



by wolf96 2017/7/19



以上是关于c#中Class和Struct使用与性能的区别的主要内容,如果未能解决你的问题,请参考以下文章

[C#基础知识]Class和Struct的区别

struct和class在C++和C#中的区别

struct和class在C++和C#中的区别

Struct和Class,值类型与引用类型(堆栈简单一提)

关于时间和空间复杂度的优化心得分享(C# )

struct与class的区别