c#中class和struct区别

2024-06-20 23:18
文章标签 c# 区别 .net class struct netcore

本文主要是介绍c#中class和struct区别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

C#将数据分为两种:值数据类型和引用数据类型,这两种数据类型存储在内存中的不同的地方:值类型数据存储在栈中,而引用类型数据存储在内存的堆中。 

预备知识

1、内存简介 

Windows使用一个系统:虚拟寻址系统。这个系统的作用是将程序可用的内存地址映射到硬件内存中的实际地址上。其实际结果就是32位的机子上每个进程都可以使用4GB的内存,当然,64位机这个数字就大了去了。这4GB的内存实际上包含了程序的所有的部分:可执行代码,DLL以及程序运行时使用的所有变量的内容。这个4GB的内存称为虚拟地址空间或虚拟内存。为方便,这里成为内存。 

4GB中的每个存储单元都是从零开始向上存储的。要访问存储在内存中的某个空间中的,就必须提供表示该存储单元的一个数字。在高级编程语言中,编译器的一个重要作用就是负责将人们可以理解的变量名称变为处理器可以理解的内存地址。 

2、栈 (stack)

在内存中,有一个区域成为栈,对象成员的值数据类型调用方法时,传递给所有方法的是参数的副本。注意:调用方法时,栈存储的是所有参数的副本,因此,经值类型A传递给函数,A的值是不会变化的。当然,引用类型是会变化的,因为在堆中存储的是引用类型的地址,这在后面会有详细的介绍。 

下面以一个例子来说明栈的工作方式,如下面的代码2

  1. {
  2. int a;
  3. //dosomething;
  4. {
  5. int b;
  6. //dosomething
  7. }
  8. }


首先声明a,在内部的代码块中声明b,然后内部的代码块终止,b就出了作用域,最后a出作用域。所以b的生命周期总是包含在a的生命周期内,在释放变量的时候,其顺序总是和分配内存的顺序是相反的。即:变量的生存周期都是嵌套的。这就是栈的工作方式。 

3、堆 (heap)

栈具有相当高的性能,但是变量的生命周期必须是嵌套的,这个要求在有的时候过于苛刻。我们希望有一种别的方法来分配内存,存储一些数据,并在方法退出的很长一段时间内,这些数据仍然是可用的,这时,就使用堆。 堆是内存中的另外一个区域,我们仍然用一个例子来说明堆的工作方式,如下面代码: 

  1. {
  2. Customer customer1; //栈
  3. customer1= new Customer(); //堆
  4. Customer customer2= new Customer();
  5. //do something
  6. }


首先,声明一个Customer  customer1,在栈上给这个引用分配存储空间。请注意:仅仅是给这个引用分配存储空间,并不是实际的Customer对象。customer1占用4个字节的空间(32位机),来表示Customer对象在内存中的地址。 然后,执行第二行代码,完成以下操作:在堆上分配存储空间,用来存储Customer对象,注意:这里是Customer对像。将变量customer1的值设为分配给Customer对象的内存地址。从这个例子中可以看出,建立引用类型的变量的过程要比建立值类型变量的过程复杂,且不避免的有性能的降低。但是,我们可以将一个引用变量的值赋给另一个引用变量,当一个变量出作用域时,它会从栈中删除,但是对象的数据仍然保留在内存中,直到程序停止。 

这样,我们在将一个引用变量A传递给函数时,仅仅是将变量A的引用传递给了函数,即:仅仅是在栈上分配内存,即变量B两者指向同一个内存地址。因此,当变量B发生变化时,变量A也会发生变化。

1、class 是引用类型,struct是值类型

引用类型的值可以设置为null,即class类型的值可以设置为null而struct类型的值不可以。

因为它是值类型(因为值类型变量直接在Stack中保存了数据,因此在生命周期结束前数据不能被任何形式的销毁,而引用类型变量在Heap中保存数据,所以赋值null其实是将对应在Heap中的数据销毁而不是结束变量的生命周期2)。

  1. struct AStruct
  2. {
  3. int aField;
  4. }
  5. class AClass
  6. {
  7. int aField;
  8. }
  9. class MainClass
  10. {
  11. public static void Main()
  12. {
  13. AClass b = null; // No error.
  14. AStruct s = null; // Error [ Cannotconvert null to 'AStruct'because //it is a value type ].
  15. }
  16. }


同时,值类型和引用类型具备的特点他们分别具备。

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. namespace struct_class
  6. {
  7. class TheClass
  8. {
  9. public int x;
  10. }
  11. struct TheStruct
  12. {
  13. public int x;
  14. }
  15. class TestClass
  16. {
  17. public static void structtaker(TheStruct s)
  18. {
  19. s.x = 5;
  20. }
  21. public static void classtaker(TheClass c)
  22. {
  23. c.x = 5;
  24. }
  25. public static void Main()
  26. {
  27. TheStructa = new TheStruct();
  28. TheClass b = new TheClass();
  29. a.x = 1;
  30. b.x = 1;
  31. structtaker(a);
  32. classtaker(b);
  33. Console.WriteLine( "a.x ={0}", a.x);
  34. Console.WriteLine( "b.x ={0}", b.x);
  35. Console.ReadKey();
  36. }
  37. }
  38. }
  39. //a.x=1
  40. //b.x=5


2、关于初始化

struct可以不使用new关键字初始化,而class必须使用new关键字初始化,但是如果不用new对struct对象进行初始化,将不能调用struct对象的方法,除非对struct中的每个字段进行初始化。

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. namespace struct_class
  6. {
  7. struct MyStruct
  8. {
  9. public int i;
  10. public string j;
  11. public void showMsg()
  12. {
  13. Console.WriteLine( "aaaa");
  14. Console.ReadKey();
  15. }
  16. }
  17. public class TestStruct
  18. {
  19. public static void Main()
  20. {
  21. MyStruct astruct;
  22. //MyStructastruct=new Mystruct();
  23. astruct.i = 1;
  24. astruct.j = "a";
  25. astruct.showMsg();
  26. }
  27. }
  28. }


3、关于继承

class支持继承和多态,Struct不支持. 注意:但是Struct 可以和类一样实现接口

4、关于构造函数

classs可以声明无参构造函数,可以声明析构函数;而struct只能声明带参数构造函数,每个字段都要进行初始化,且不能声明析构函数。因此,struct没有自定义的默认无参构造函数,默认无参构造器只是简单地把所有的值初始它的的0等价值。

这篇关于c#中class和struct区别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1079542

相关文章

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当

详解C#如何提取PDF文档中的图片

《详解C#如何提取PDF文档中的图片》提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使用,下面我们就来看看如何使用C#通过代码从PDF文档中提取图片吧... 当 PDF 文件中包含有价值的图片,如艺术画作、设计素材、报告图表等,提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法

C#使用SQLite进行大数据量高效处理的代码示例

《C#使用SQLite进行大数据量高效处理的代码示例》在软件开发中,高效处理大数据量是一个常见且具有挑战性的任务,SQLite因其零配置、嵌入式、跨平台的特性,成为许多开发者的首选数据库,本文将深入探... 目录前言准备工作数据实体核心技术批量插入:从乌龟到猎豹的蜕变分页查询:加载百万数据异步处理:拒绝界面

C#数据结构之字符串(string)详解

《C#数据结构之字符串(string)详解》:本文主要介绍C#数据结构之字符串(string),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录转义字符序列字符串的创建字符串的声明null字符串与空字符串重复单字符字符串的构造字符串的属性和常用方法属性常用方法总结摘

C#如何动态创建Label,及动态label事件

《C#如何动态创建Label,及动态label事件》:本文主要介绍C#如何动态创建Label,及动态label事件,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#如何动态创建Label,及动态label事件第一点:switch中的生成我们的label事件接着,

C# WinForms存储过程操作数据库的实例讲解

《C#WinForms存储过程操作数据库的实例讲解》:本文主要介绍C#WinForms存储过程操作数据库的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、存储过程基础二、C# 调用流程1. 数据库连接配置2. 执行存储过程(增删改)3. 查询数据三、事务处

分辨率三兄弟LPI、DPI 和 PPI有什么区别? 搞清分辨率的那些事儿

《分辨率三兄弟LPI、DPI和PPI有什么区别?搞清分辨率的那些事儿》分辨率这个东西,真的是让人又爱又恨,为了搞清楚它,我可是翻阅了不少资料,最后发现“小7的背包”的解释最让我茅塞顿开,于是,我... 在谈到分辨率时,我们经常会遇到三个相似的缩写:PPI、DPI 和 LPI。虽然它们看起来差不多,但实际应用

C#基础之委托详解(Delegate)

《C#基础之委托详解(Delegate)》:本文主要介绍C#基础之委托(Delegate),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 委托定义2. 委托实例化3. 多播委托(Multicast Delegates)4. 委托的用途事件处理回调函数LINQ