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

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

我们来看下面一段代码:

    首先在类中声明一个class类,和一个struct结构,如图:

  并使用在程序入口调用它们,如图

    现在我们来看一看,它们在内存当中是如何存储的?

从这张图可以看出,class(类)实例化出来的对象,指向了内存堆中分配的空间

struct(结构) 实例化出来的对象,是在内存栈中分配

   接下来,我们再来在上面的程序做如下修改:

   

红框,代码定义一个class实例化对象s2,然后把对象s1赋值给s2

    蓝框,代码定义一个结构实例化对象r2,然后把对象r1赋值给r2

    那它们输出的结果是多少呢?请选择(   )

   

A、  s1的值为:12     s2的值为222
       r1的值为:16     r2的值为666

B、  s1的值为:12     s2的值为222
       r1的值为:666    r2的值为666

C、  s1的值为:222    s2的值为222
       r1的值为:16     r2的值为666

D、  s1的值为:222     s2的值为222
       r1的值为:666     r2的值为666

正确答案是:C

为什么会这样呢?所以我们来看一看,多个值类型和引用类型在内存里面是如何存储的,如图:

从图中,可以看出,两个引用类型 s1,s2都指向了同一个拖管堆上的空间,

当某一个发生改变的时候,其于的会发生变化

而结构是值类型,虽然使用r2=r1,把r1对象赋值给r2,

但是它会在线程栈中分配一个独立的空间,

     当修改某一个对象的值的时候,不会影响到另一个对象

   所以,值类型和引用类型的区别就是:

            1、它们存储的位置不一样

            2、如果是引用类型,当两个对象指向同一个地方,修改某一个的时候,其它对象的值会发生改变

  案例代码下载

时间: 2024-10-10 10:02:09

c#中Class和Struct使用与性能的区别的相关文章

c#中结构体(struct)和类(class)的区别

一.类与结构的示例比较: 结构示例: public struct Person { string Name; int height; int weight public bool overWeight() { //implement something } } 类示例: public class TestTime { int hours; int minutes; int seconds; public void passtime() { //implementation of behavior

ASP.NET中常用的26个优化性能方法

1. 数据库访问性能优化 数据库的连接和关闭 访问数据库资源需要创建连接.打开连接和关闭连接几个操作.这些过程需要多 次与数据库交换信息以通过身份验证,比较耗费服务器资源.ASP.NET 中提供了 连接池(Connection Pool)改善打开和关闭数据库对性能的影响.系统将用户的 数据库连接放在连接池中,需要时取出,关闭时收回连接,等待下一次的连接请 求.连接池的大小是有限的,如果在连接池达到最大限度后仍要求创建连接,必 然大大影响性能.因此,在建立数据库连接后只有在真正需要操作时才打开连接

Web标准中用于改善Web应用程序性能的各种方法总结

提起Web应用程序中的性能改善,广大开发者们可能会想到JavaScript与DOM访问等基于各种既存技术的性能改善方法.最近,各种性能改善方法被汇总成为一个Web标准. 本文对Web标准中所包含的各种Web应用程序性能改善方法做一总体介绍. 1:预先读取资源 通过在link标签中指定URL将接下来极有可能要读取的Web页面或页面中的资源预先读取.例如通过对于向导页面中的“下一步”页面,登录页面中登录后的主画面中所用大尺寸的JavaScript框架中的核心文件等页面或资源文件的读取,可以大幅度提高

SQLServer中的页如何影响数据库性能 (转)

无论是哪一个数据库,如果要对数据库的性能进行优化,那么必须要了解数据库内部的存储结构.否则的话,很多数据库的优化工作无法展开.对于对于数据库管理员来说,虽然学习数据库的内存存储结构比较单调,但是却是我们必须攻下的一个堡垒.在SQLServer数据库中,数据页是其存储的最基本单位.系统无论是在保存数据还是在读取数据的时候,都是以页为单位来进行操作的. 一.数据页的基本组成. 如上图所示,是SQLServer数据库中页的主要组成部分.从这个图中可以看出,一个数据页基本上包括三部分内容,分别为标头.数

MySQL中使用SHOW PROFILE命令分析性能的用法整理(配合explain效果更好,可以作为优化周期性检查)

这篇文章主要介绍了MySQL中使用show profile命令分析性能的用法整理,show profiles是数据库性能优化的常用命令,需要的朋友可以参考下 show profile是由Jeremy Cole捐献给MySQL社区版本的.默认的是关闭的,但是会话级别可以开启这个功能.开启它可以让MySQL收集在执行语句的时候所使用的资源.为了统计报表,把profiling设为1 mysql> SET profiling = 1; 之后在运行一个查询 mysql> SELECT COUNT(DIS

ASP.NET中常用的26个优化性能方法(转)

1. 数据库访问性能优化 数据库的连接和关闭 访问数据库资源需要创建连接.打开连接和关闭连接几个操作.这些过程需要多次与数据库交换信息以通过身份验证,比较耗费服务器资源.ASP.NET中提供了连接池(Connection Pool)改善打开和关闭数据库对性能的影响.系统将用户的数据库连接放在连接池中,需要时取出,关闭时收回连接,等待下一次的连接请求.连接池的大小是有限的,如果在连接池达到最大限度后仍要求创建连接,必然大大影响性能.因此,在建立数据库连接后只有在真正需要操作时才打开连接,使用完毕后

C++中class与struct的区别(struct的类型名同时可以作为变量名)

通常我们知道的区别: (一)默认继承权限.如果不明确指定,来自class的继承按照private继承处理,来自struct的继承按照public继承处理: (二)成员的默认访问权限.class的成员默认是private权限,struct默认是public权限. 除了这两点,class和struct基本就是一个东西.语法上没有任何其它区别. 昨天发现一个不知道算不算是区别的东西: struct的类型名同时可以作为变量名,显然class是不可以的,也可以理解,因为class各类型变量定义时直接是类名

修改Dictionary或List中结构体struct值的问题

问题:修改Dictionary中结构体struct值的值,如果直接用Dictionary[key].a += XX;(a为结构体中某数值型属性) ,则会报错: 无法修改.Dictionary<int,struct>.this[int]”的返回值,因为它不是变量 如果用一个变量承接Dictionary[key]中的结构体,即struct newStr =Dictionary[key],然后再做出修改:newStr.a += XX,则Dictionary中对应的结构体的值不发生变化.(由此可判断结

[ASP.NET]ASP.NET中常用的26个优化性能方法

1. 数据库访问性能优化 数据库的连接和关闭 访问数据库资源需要创建连接.打开连接和关闭连接几个操作.这些过程需要多次与数据库交换信息以通过身份验证,比较耗费服务器资源.ASP.NET中提供了连接池(Connection Pool)改善打开和关闭数据库对性能的影响.系统将用户的数据库连接放在连接池中,需要时取出,关闭时收回连接,等待下一次的连接请求.连接池的大小是有限的,如果在连接池达到最大限度后仍要求创建连接,必然大大影响性能.因此,在建立数据库连接后只有在真正需要操作时才打开连接,使用完毕后