翻译自 Manju lata Yadav 2019年6月2日 的博文 《Difference Between Struct And Class In C#》,补充了一些内容和示例。

结构体(struct)是类(class)的轻量级版本。结构体是值类型,可用于创建行为类似于内置类型的对象。

比较

结构体和类共享许多特性,但与类相比有以下局限性。

  • 结构体不能有默认构造函数(无参构造函数)或析构函数,构造函数中必须给所有字段赋值。

      public struct Coords{public double x;public double y;public Coords() //错误,不允许无参构造函数{this.x = 3;this.y = 4;}public Coords(double x) //错误,构造函数中必须给所有字段赋值{this.x = x;}public Coords(double x) //这个是正确的{this.x = x;this.y = 4;}public Coords(double x, double y) //这个是正确的{this.x = x;this.y = y;}}
    
  • 结构体是值类型,在赋值时进行复制。

  • 结构体是值类型,而类是引用类型。

  • 结构体可以在不使用 new 操作符的情况下实例化。例如:

      public struct Coords{public double x;public double y;}static void Main(){Coords p;p.x = 3;p.y = 4;Console.WriteLine($"({p.x}, {p.y})");  // 输出: (3, 4)}
    
  • 结构体不能继承于另一个结构体或者类,类也不能继承结构体。所有结构体都直接继承于抽象类 System.ValueTypeSystem.ValueType 又继承于 System.Object

  • 结构体不能是基类,因此,结构体不能是 abstract 的,且总是隐式密封的(sealed)。

  • 不允许对结构体使用抽象(abstract)和密封(sealed)修饰符,也不允许对结构体成员使用 protected 或 protected internal 修饰符。

  • 结构体中的函数成员不能是抽象的(abstract)或虚的(virtual),重写(override)修饰符只允许重写从 System.ValueType 继承的方法。

  • 结构体中不允许实例属性或字段包含初始值设定项。但是,结构体允许静态属性或字段包含初始值设定项。例如:

      public struct Coords{public double x = 4; //错误, 结构体中初始化器不允许实例字段设定初始值public static double y = 5; // 正确public static double z { get; set; } = 6; // 正确}
    
  • 结构体可以实现接口。

  • 结构体可以用作 nullable type(即:Nullable<T> 中的 T),对其赋值 null 值,参考【Nullable<T> Struct (https://docs.microsoft.com/en-us/dotnet/api/system.nullable-1?view=netcore-3.1)】

什么时候使用结构体或类?

要回答这个问题,我们应该很好地理解它们的差异。

序号 结构体(struct 类(class)
1 结构体是值类型,可以在栈(stack)上分配,也可以在包含类型中内联分配。 类是引用类型,在堆(heap)上分配并垃圾回收。
2 值类型的分配和释放通常比引用类型的分配和释放更节约成本。 大的引用类型的赋值比大的值类型的赋值成本更低。
3 在结构体中,每个变量都包含自己的数据副本(ref 和 out 参数变量除外),对一个变量的操作不会影响另一个变量。 在类中,两个变量可以包含同一对象的引用,对一个变量的任何操作都会影响另一个变量。

这样,结构体(struct)只能在确定以下情形时使用:

  • 它在逻辑上表示单个值,比如基本类型(intdouble,等等)。

  • 它是不可变的(immutable)。

  • 它不会频繁地装箱和拆箱。

在所有其他情形,应该将类型定义为类(class)。

结构体示例:

struct Location
{public int x, y;public Location(int x, int y){this.x = x;this.y = y;}
}static void Main()
{Location a = new Location(20, 20);Location b = a;a.x = 100;Console.WriteLine(b.x);
}

输出将是 20。“b” 的值是 “a” 的副本,因此 “b” 不受 “a.x” 更改的影响。但是在类中,输出将是 100,因为变量 “a” 和 “b” 引用同一个对象。

以下为译者补充

结构体实例与类实例

结构体实例的内存在栈(stack)上进行分配,所占用的内存随声明它的类型或方法一起回收。这就是在赋值时要复制结构体的一个原因。相比之下,类实例的内存在堆(heap)上进行分配,当对类实例的所有引用都超出范围时,为该类实例分配的内存将由公共语言运行时自动回收(垃圾回收)。

结构体实例的值相等性

两个结构体实例的比较是基于值的比较,而类实例的比较则是对其引用的比较。

若要确定两个结构体实例中的实例字段是否具有相同的值,可使用 ValueType.Equals 方法。由于所有结构体都隐式继承于 System.ValueType,因此可以直接在其对象上调用该方法,如以下示例所示:

public struct Person
{public string Name;public int Age;public Person(string name, int age){Name = name;Age = age;}
}static void Main()
{Person p1 = new Person("技术译站", 100);Person p2;p2.Name = "技术译站";p2.Age = 100;if (p2.Equals(p1))Console.WriteLine("p2 和 p1 有相同的值。");Console.ReadKey();
}
// 输出: p2 和 p1 有相同的值。

System.ValueType 的 Equals 是使用反射实现,因为它必须能够确定任何结构体中有哪些字段。在创建自己的结构体时,重写 Equals 方法可以提供特定于你的类型的高效求等算法。

“基于值的相等”这一点和 C# 9.0 中新增的记录(record) 类型具有相似之处,想了解 C# 9.0 可以查看:欢迎来到 C# 9.0。

作者 : Manju lata Yadav 
译者 :技术译民
出品 :技术译站(https://ITTranslator.cn/)

C# 中 Struct 和 Class 的区别总结相关推荐

  1. C与C++中struct及C++中struct与class的区别

    C++中struct与class的区别 struct class 备注 成员函数 能 能 均有构造函数及析构函数 继承性 能 能 多态性 能 能 均有虚函数 默认成员属性 public private ...

  2. C#中struct和class的区别详解

    本文详细分析了C#中struct和class的区别,对于C#初学者来说是有必要加以了解并掌握的. 简单来说,struct是值类型,创建一个struct类型的实例被分配在栈上.class是引用类型,创建 ...

  3. C# 中 Struct 与 Class 的区别,以及两者的适用场合

    C# 中 Struct 与 Class 的区别,以及两者的适用场合 先说区别,原文出处 http://www.dotnetspider.com/resources/740-Difference-bet ...

  4. C#中Struct与Class的区别

    class和struct最本质的区别是class是引用类型,而struct是值类型,它们在内存中的分配情况有所区别. 什么是class? class(类)是面向对象编程的基本概念,是一种自定义数据结构 ...

  5. C++中Struct和Class的区别

    Struct和Class的区别 今天这篇博文主要讲解在C++中关键字struct和class的区别.这篇博文,将会系统的将这两个关键字的不同面进行详细的讲解. 从语法上来讲,class和struct做 ...

  6. c#中struct和class的区别

    简单来说,struct是值类型,创建一个struct类型的实例被分配在栈上.class是引用类型,创建一个class类型实例被分配在托管堆上.但struct和class的区别远不止这么简单.本篇主要包 ...

  7. C++_类和对象_封装_访问权限_C++中struct和class的区别---C++语言工作笔记037

    然后我们再来看c++中的访问权限控制,其实这个跟java中的很像 可以看到有3个,public 是类内类外都可以访问 protected 是保护权限,在类内可以访问,但是在类外不行.  这个在子类的时 ...

  8. C#中struct和class的使用区别是什么?

    class是引用类型,struct是值类型 引用类型在堆上,值类型是内联的. 值类型有全部的值的内容,而引用类型只有一个地址. 值类型总是有一个值,而引用类型指针可以为空. 为了优化减少体积 需要传递 ...

  9. C++中结构体与类的区别(struct与class的区别)

    C++中的struct对C中的struct进行了扩充,它已经不再只是一个包含不同数据类型的数据结构了,它已经获取了太多的功能. struct能包含成员函数吗? 能! struct能继承吗? 能!! s ...

最新文章

  1. 2021高考成绩各科各题得分查询,2021年新疆高考分数一分一段位次表,新疆高考个人成绩排名查询方法...
  2. iOS 13 Xcode11 中的 Scene Delegate
  3. linux文字全选_linux编写脚本全选注释素材
  4. Android开发:操作UI线程4种方法
  5. 静态初始化块的执行顺序
  6. 问题 | 0x00007FF95287908C 处(位于 OpenCV.exe 中)有未经处理的异常: Microsoft C++ 异常: cv::Exception
  7. 笑死了,打错一个字,竟然...
  8. CISSP的成长之路(二十一):用户持有凭证
  9. 领域驱动专家张逸文字脱口秀:简单工厂不简单
  10. 使用 javascript 标记高亮关键词
  11. 陀螺研究院 | 产业区块链发展周报(11.7—11.13)
  12. sprintf函数的使用方法
  13. 打造自己的ip代理池
  14. 通过lan从服务器启动系统,OPNsense启用LAN网桥
  15. redis 模糊删除keys
  16. 蓝牙mesh- Features和设备类型
  17. 微信小程序 申请第三方平台流程
  18. 什么平台制作表单工具效率高?
  19. 岁月安好,不存在的!不过是有人替你负重前行
  20. LeetCode(871):最低加油次数 Minimum Number of Refueling Stops(Java)

热门文章

  1. 如何完善自己的知识结构
  2. Bootstrap入门(八)组件2:下拉菜单
  3. 一头扎进Node(三) - File System
  4. MySQL For RedHat Linux(源码安装,附安装包)
  5. 一步步学习微软InfoPath2010和SP2010--第八章节--使用InfoPath表单Web部件
  6. IUnknown接口QueryInterface函数介绍
  7. 变动翻屏展示图片效果
  8. Django中session和cookie简单的使用
  9. 关于经纬度的两个计算[Teaksxgluxv]
  10. 无法打开物理文件“E:\Database\VRVIES6841-FZ01-Global\VRVEIS.mdf”。操作系统错误 5:“5(拒绝访问。)”...