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

相关文章

C#比较两个List集合内容是否相同的几种方法

《C#比较两个List集合内容是否相同的几种方法》本文详细介绍了在C#中比较两个List集合内容是否相同的方法,包括非自定义类和自定义类的元素比较,对于非自定义类,可以使用SequenceEqual、... 目录 一、非自定义类的元素比较1. 使用 SequenceEqual 方法(顺序和内容都相等)2.

java中不同版本JSONObject区别小结

《java中不同版本JSONObject区别小结》本文主要介绍了java中不同版本JSONObject区别小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们... 目录1. FastjsON2. Jackson3. Gson4. org.json6. 总结在Jav

在Rust中要用Struct和Enum组织数据的原因解析

《在Rust中要用Struct和Enum组织数据的原因解析》在Rust中,Struct和Enum是组织数据的核心工具,Struct用于将相关字段封装为单一实体,便于管理和扩展,Enum用于明确定义所有... 目录为什么在Rust中要用Struct和Enum组织数据?一、使用struct组织数据:将相关字段绑

C#使用DeepSeek API实现自然语言处理,文本分类和情感分析

《C#使用DeepSeekAPI实现自然语言处理,文本分类和情感分析》在C#中使用DeepSeekAPI可以实现多种功能,例如自然语言处理、文本分类、情感分析等,本文主要为大家介绍了具体实现步骤,... 目录准备工作文本生成文本分类问答系统代码生成翻译功能文本摘要文本校对图像描述生成总结在C#中使用Deep

C#从XmlDocument提取完整字符串的方法

《C#从XmlDocument提取完整字符串的方法》文章介绍了两种生成格式化XML字符串的方法,方法一使用`XmlDocument`的`OuterXml`属性,但输出的XML字符串不带格式,可读性差,... 方法1:通过XMLDocument的OuterXml属性,见XmlDocument类该方法获得的xm

C#多线程编程中导致死锁的常见陷阱和避免方法

《C#多线程编程中导致死锁的常见陷阱和避免方法》在C#多线程编程中,死锁(Deadlock)是一种常见的、令人头疼的错误,死锁通常发生在多个线程试图获取多个资源的锁时,导致相互等待对方释放资源,最终形... 目录引言1. 什么是死锁?死锁的典型条件:2. 导致死锁的常见原因2.1 锁的顺序问题错误示例:不同

数据库使用之union、union all、各种join的用法区别解析

《数据库使用之union、unionall、各种join的用法区别解析》:本文主要介绍SQL中的Union和UnionAll的区别,包括去重与否以及使用时的注意事项,还详细解释了Join关键字,... 目录一、Union 和Union All1、区别:2、注意点:3、具体举例二、Join关键字的区别&php

java中的HashSet与 == 和 equals的区别示例解析

《java中的HashSet与==和equals的区别示例解析》HashSet是Java中基于哈希表实现的集合类,特点包括:元素唯一、无序和可包含null,本文给大家介绍java中的HashSe... 目录什么是HashSetHashSet 的主要特点是HashSet 的常用方法hasSet存储为啥是无序的

C#提取PDF表单数据的实现流程

《C#提取PDF表单数据的实现流程》PDF表单是一种常见的数据收集工具,广泛应用于调查问卷、业务合同等场景,凭借出色的跨平台兼容性和标准化特点,PDF表单在各行各业中得到了广泛应用,本文将探讨如何使用... 目录引言使用工具C# 提取多个PDF表单域的数据C# 提取特定PDF表单域的数据引言PDF表单是一

C#实现添加/替换/提取或删除Excel中的图片

《C#实现添加/替换/提取或删除Excel中的图片》在Excel中插入与数据相关的图片,能将关键数据或信息以更直观的方式呈现出来,使文档更加美观,下面我们来看看如何在C#中实现添加/替换/提取或删除E... 在Excandroidel中插入与数据相关的图片,能将关键数据或信息以更直观的方式呈现出来,使文档更