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


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

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

    值类型与引用类型的区别这两篇文章讲得很好
     
    虽然我们在.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.***** = ****;
    值类型后面加问号表示可为空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
     
  • 相关阅读:
    Delphi中Format与FormatDateTime函数详解
    常用的日期时间函数
    100m和1000m网线的常见制作方法
    Delphi cxGrid –--> RecordIndex out of Range
    局域网共享需要密码
    提高AdoQuery的速度
    string literals may have at most 255 elements
    001-project基本使用
    Java-idea-创建maven项目,部署项目,部署服务器,简单测试
    003-spring结合java类调用quartz
  • 原文地址:https://www.cnblogs.com/zhanlang96/p/7259190.html
Copyright © 2020-2023  润新知