微软.NET6开发的C#特性——类、结构体和联合体

我是荔园微风,作为一名在IT界整整25年的老兵,看到不少初学者在学习编程语言的过程中如此的痛苦,我决定做点什么,下面我就重点讲讲微软.NET6开发人员需要知道的C#特性。

C#经历了多年发展, 进行了多次重大创新, 大幅优化了开发者的编码体验。在.NET 平台移交给.NET基金会运营后, C#更新的越来越不像原来的C#了,但总体上来说,所有改进依然以优化开发者的编码体验为最终目的。

首先,要记住一张表,如下:

C#版本     发布时间         .NET版本                       VS版本                  CLR版本

C#1.0        2002-2-13       .NET Framework 1.0     VS.NET 2002      .NET Framework CLR 1.0

C#2.0        2005-11-7       .NET Framework 2.0     VS2005               .NET Framework CLR 2.0

C#3.0        2006-11-6       .NET Framework 3.0     VS2008               .NET Framework CLR 2.0 

C#3.0       2007-11-19     .NET Framework 3.5     VS2008                .NET Framework CLR 2.0 

C#4.0       2010-4-12       .NET Framework 4.0     VS2010                .NET Framework CLR 4.0

C#5.0       2012-2-20        .NET Framework 4.5     VS2012               .NET Framework CLR 4.0

C#6.0       2015-7-26        .NET Framework 4.6      VS2015              .NET Framework CLR 4.0

C#7.0       2016-8-2          .NET Framework 4.6.2    VS2017(v15)     .NET Framework CLR 4.0

C#7.1       2017-4-5          .NET Framework 4.7      VS2017(v15.3)   .NET Framework CLR 4.0

C#7.2       2017-10-17      .NET Framework 4.7.1   VS2017(v15.5)    .NET Framework CLR 4.0

C#7.3       2018-4-30         .NET Framework 4.7.2   VS2017(v15.8)   .NET Framework CLR 4.0

C#8.0       2019-4-18          .NET Framework 4.8    VS2019(v16.3)    .NET Framework CLR 4.0

C#8.0       2019-9-24         .NETCore 3.0                 VS2019(v16.4)    .NETCore CLR 3.0       

C#9.0       2020-11-10       .NET 5.0                        VS2019(v16.8)    .NET CLR 5.0           

C#10.0     2021-11-8         .NET 6.0                        VS2022(v17)       .NET CLR 6.0 

看完这张表,我真的是很感慨,从测试版开始,我居然陪伴着.NET和C#走过了二十多年,我不知道有没有微软公司的人在看这篇文章,如果有的话,不知道我这样的二十多年的.NET和C#程序员有没有机会去微软中国和微软亚洲研究院的总部去参观一下,去坐一坐,并作一下技术交流。二十多年了,人生又有几个二十多年。

.NET平台是基于IL中间语言的应用运行环境,面向对象语言C#是平台的主要开发语言。除此之外还有同样面向对象的C++/CLI。C++/CLI主要用于和原生C++交互,在.NET平台中仅支持Windows系统。

C#和.NET平台本来是微软为了与Java平台竞争而打造的,C#在设计时充分总结了Java的经验教训,解决了大量Java的基本设计缺陷。本着为一线开发者谋实惠的宗旨,C#设计了大量能减轻开发者的编写负担、容易理解且安全高效的实用功能。为了尽可能降低因安全措施导致性能大幅下降的影响,C#还在有限的情况下保留了C/C++语言的部分语法和功能。到了.NET时代,微软依然在运行时(Runtime)和语言两边同时进行着优化。

随着上世纪九十年代Java的发布,软件公司和开发者开始感受到基于虚拟机的托管语言所带来的好处,微软也不甘示弱,在2001年发布了.NET Framework平台和C#。提供了完整的基础面向对象支持。

类、结构体和联合体

类和结构体是从C/C++继承的功能,结构体从C语言开始就作为供开发者自定义数据结构的基本功能出现,在C++中升级为了面向对象的类。C++的类和结构体并没有明确的概念和功能上的差别,Java删除了结构体这个概念,只保留了类。微软发现了能够有效利用这两个概念的方法,因此C#保留了类和结构体。

Java和C#都有一套完善的类型系统,所有的类型都是直接或间接地由 Object派生而来。但不知为何Java有基元类型。基元类型基本代表了在C/C++中由编译器和CPU直接支持的原始类型,而这些类型却不属于类型系统。为了解决这个问题,Java又设计了一套包装类型。这带来一个问题,类型系统是Java的根基,但作为其中的基石的基元类型居然和类型系统不兼容,这也在后来为Java带来了更多的麻烦。

C#却巧妙地利用了类和结构体完成了没有内生矛盾的类型系统,一切类型都是Object的后代,包括基本数据类型。在C#的设计中,基本类型的继承路径是 System.Object→System.ValueType→各种基本类型。

ValueType禁止使用常规语法继承,并且其子类是强制封闭的,禁止继续继承。这时结构体就派上用场了,结构体就是隐式继承了ValueType的封闭类型,基本数据类型就是由.NET预定义的结构体。结构体是直接在线程栈上分配的免回收类型,拥有极高的性能。也因为在栈上的分配必须静态确定其占用的内存空间并直接分配,因此结构体禁止赋值为null。

由于结构体的复制策略是深拷贝,因此在方法之间作为参数传递时传递的是完整的独立副本,互不影响,和普通类的引用拷贝形成了鲜明的对比。为了保持和Object的完整兼容性,.NET还特地为结构体准备了自动装箱和拆箱。装箱即是指在显式或隐式转换为Object类型的时候运行时自动在托管堆上分配对象内存并把值复制到对象中;拆箱即是指在显式或隐式转换回原类型时自动在线程栈上分配内存并把值从托管堆复制到栈上。托管堆中的对象占用的内存一般比线程栈上的大,因为堆对象占用的内存除了基本值所需内存之外还包含类型对象指针和同步块索引(C#的lock同步锁语句块就是依靠同步块索引实现的)等额外信息,而栈上的结构体实例只占用基本值所需的内存。经过这些周密的设计,C#拥有了完美自治的类型系统,类和结构体也拥有了明显的功能区分。

在C++中有一个被称为友元类的功能,友元类之间允许相互访问对方的私有成员,这在一定程度上破坏了类的封装性,因此Java和C#都删除了这个功能。不过C#却有一个被称为友元程序集的功能,友元程序集的类之间允许互相访问对方的内部(internal)成员,这在编写单元测试时经常用到。由于C#和Java都是托管语言,因此都可以通过反射彻底绕过成员访问保护机制,C/C++也可以通过万能的指针绕过编译器保护。

C#、C、C++、Java的类和结构体的代码如下。

(1)C#

//结构体
public struct Point2D
{public double x;public double y;
}//类
public class Point3D{public double x;public double y;public double z; 
} //抽象类 
public abstract class MyClass 
{ public abstract void Method1(); public virtual void Method2() {} 
} 

(2)C

typedef struct {double x; double y; 
} Point 2D; 

(3)C++

① Point3D.h

#pragma once class Point3D 
{ public: double x; double y; double z; 
}; class MyClass 
{ public: virtual void Method1() =0; virtual void Method2();
};

② Point3D.cpp

#include"Point3D.h" void MyClass::Method2() {} 

(4) Java

public class Point3D { public double x; public double y; public double z; 
}public abstract class MyClass{ public abstract void method1(); public void method2() {}
} 

在C语言中有一种独特的数据结构叫作联合体,它的特点是所有数据成员共享内存空间,并且同一时刻最多只有一个成员处于可用状态。这种数据类型的诞生主要是因为C语言刚面世的时候计算机的内存还比较小, 需要尽量节约使用内存。C#和Java诞生的年代内存不再紧缺, 因此并不支持这种数据类型。但是C#为了兼容和C语言的互操作, 从.NET Framework 1.1开始支持通过特殊方式模拟联合体。 

C#在模拟联合体时,如果其中有类类型的成员,可能在运行时引发异常,因此在模拟联合体时一般只用结构体类型的成员,当然,虽然读取非激活状态的成员不会引发异常,但是仍然可能读取到错误的值。在C语言的联合体中通常也只使用基本数据类型。

C的联合体和C#的模拟联合体示例代码分别如下所示。

(1) C

typedef union {int x;float y;double z;
} MyUnion;


(2)C#

using System. Runtime.InteropServices;namespace Example
{//手动定义结构体布局,占用8字节空间[StructLayout (LayoutKind. Explicit, Size =8)]public struct MyUnion{//字段偏移量为0,实际占用4字节,剩下4字节不使用[Fieldoffset(0)]public int x;//字段偏移量为0,实际占用4字节,剩下4字节不使用[Fieldoffset(0)]public float y;//字段偏移量为0,刚好用完8个字节[Fieldoffset (0)]public double z;}
}

C#使用结构体模拟联合体时,StructLayout特性可以告知运行时(Runtime)开发者要手动定义结构体的内存布局,其中字段的FieldOffset特性告知运行时这个字段在对象中的内存偏移量,示例中全部指定为0就表示所有成员共享相同的内存空间。上面代码中的各个字段所需的内存空间不尽相同,因此当需求内存较小的成员处于激活状态时,多余的内存会处于空闲状态。
 

作者简介:荔园微风,1981年生,高级工程师,浙大工学硕士,软件工程项目主管,做过程序员、软件设计师、系统架构师,早期的Windows程序员,Visual Studio忠实用户,C/C++使用者,是一位在计算机界学习、拼搏、奋斗了25年的老将,经历了UNIX时代、桌面WIN32时代、Web应用时代、云计算时代、手机安卓时代、大数据时代、ICT时代、AI深度学习时代、智能机器时代,我不知道未来还会有什么时代,只记得这一路走来,充满着艰辛与收获,愿同大家一起走下去,充满希望的走下去。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2774431.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Hadoop搭建(完全分布式)

节点分布: bigdata-masterbigdata-slave1bigdata-salve2 NameNode NodeManager NodeManager SecondaryNameNodeDataNodeDataNodeResourceManagerNodeManagerDataNode 目录 一、jdk安装: 二、hadoop安装 一、jdk安装: jdk-8u212链接&am…

git 使用 (备查)

git忽略清单 添加忽略清单 SSH免登录 ssh协议可以实现免登录操作,身份验证通过密钥实现。 跨团队写作 解决冲突 拉取 克隆 拉取最新版本 推送 远程仓库别名 直接使用git push推送 多人协作开发 分支命令 合并分支命令在主分支使用,将develop分支合并到…

【力扣】快乐数,哈希集合 + 快慢指针 + 数学

快乐数原题地址 方法一:哈希集合 定义函数 getNext(n) ,返回 n 的所有位的平方和。一直执行 ngetNext(n) ,最终只有 2 种可能: n 停留在 1 。无限循环且不为 1 。 证明:情况 1 是存在的,如力扣的示例一…

【C++基础入门】七、指针(定义和使用、所占内存空间、空指针和野指针、const关键字修饰指针、指针和数组、指针和函数)

七、指针 7.1 指针的基本概念 指针的作用: 可以通过指针间接访问内存 内存编号是从0开始记录的,一般用十六进制数字表示可以利用指针变量保存地址 7.2 指针变量的定义和使用 指针变量定义语法: 数据类型 * 变量名; 示例&…

深入Pandas:精通文本数据处理的20+技巧与应用实例【第68篇—python:文本数据处理】

文章目录 Pandas文本数据处理方法详解1. str/object类型转换2. 大小写转换3. 文本对齐4. 获取长度5. 出现次数6. 编码方向7. 字符串切片8. 字符串替换9. 字符串拆分10. 字符串连接11. 字符串匹配12. 去除空格13. 多条件过滤14. 字符串排序15. 字符串格式化16. 多列文本操作17. …

PHPExcel导出excel

PHPExcel下载地址 https://gitee.com/mirrors/phpexcelhttps://github.com/PHPOffice/PHPExcel 下载后目录结构 需要的文件如下图所示 将上面的PHPExcel文件夹和PHPExcel.php复制到你需要的地方 这是一个简单的示例代码 <?php$dir dirname(__FILE__); //require_once …

「Mybatis实战五」:Mybatis核心文件详解 - MyBatis常用配置environments、properties

一、MyBatis核心配置文件层级关系 ​ 本文代码在 Mybatis初体验&#xff1a;一小时从入门到运行你的第一个应用 所构建的基础代码结构之上&#xff0c;进行修改。 MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下&#xff1a; 二…

Github 2024-02-08 开源项目日报 Top9

根据Github Trendings的统计&#xff0c;今日(2024-02-08统计)共有9个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量Ruby项目1HTML项目1Python项目1Scala项目1PLpgSQL项目1Rust项目1NASL项目1C项目1TypeScript项目1非开发语言项目…

vue3:26—新的内置组件

目录 Teleport Suspense Teleport 什么是Teleport? Teleport 是一种能够将我们的组件html结构移动到指定位置的技术 当在元素中的css使用了filter滤镜属性的时候&#xff0c;会导致内部 fixed 元素定位发生错误&#xff0c;即不再相对 viewport 进行定位&#xff0c;而是相对…

Redis篇之redis是单线程

一、redis是单线程 Redis是单线程的&#xff0c;但是为什么还那么快&#xff1f;主要原因有下面3点原因&#xff1a; 1. Redis是纯内存操作&#xff0c;执行速度非常快。 2. 采用单线程&#xff0c;避免不必要的上下文切换可竞争条件&#xff0c;多线程还要考虑线程安全问题。 …

【Google Bard】免费生成图像——功能和使用方法详解

Google Bard 关于Bard 图片生成功能打开Bard通过Bard来生成图片Bard Vs Bing Vs Dall-EBard的生成结果Bing的生成结果Dall-E 的生成结果 总结 关于Bard 图片生成功能 Google在2月1日&#xff08;当地时间&#xff09;宣布&#xff0c;其对话型AI“Bard”新增了图像生成功能。 …

ICLR 2024 | Harvard FairSeg:第一个研究分割算法公平性的大型医疗分割数据集

近年来&#xff0c;人工智能模型的公平性问题受到了越来越多的关注&#xff0c;尤其是在医学领域&#xff0c;因为医学模型的公平性对人们的健康和生命至关重要。高质量的医学公平性数据集对促进公平学习研究非常必要。现有的医学公平性数据集都是针对分类任务的&#xff0c;而…

【Java】ArrayList和LinkedList的区别是什么

目录 1. 数据结构 2. 性能特点 3. 源码分析 4. 代码演示 5. 细节和使用场景 ArrayList 和 LinkedList 分别代表了两类不同的数据结构&#xff1a;动态数组和链表。它们都实现了 Java 的 List 接口&#xff0c;但是有着各自独特的特点和性能表现。 1. 数据结构 ArrayList…

泽攸科技ZEM系列台扫助力环境科研创新:可见光催化抗生素降解的探索

环境污染和能源短缺是当今人类社会面临的最严重威胁之一。为了克服这些问题&#xff0c;特别是在污水处理过程中&#xff0c;寻找新的技术来实现清洁、高效、经济的发展显得尤为重要。在各种工业废水中&#xff0c;抗生素的过量排放引起了广泛关注。抗生素的残留会污染土壤、水…

Openresty+Lua+Redis实现高性能缓存

一、背景 当我们的程序需要提供较高的并发访问时&#xff0c;往往需要在程序中引入缓存技术&#xff0c;通常都是使用Redis作为缓存&#xff0c;但是要再更进一步提升性能的话&#xff0c;就需要尽可能的减少请求的链路长度&#xff0c;比如可以将访问Redis缓存从Tomcat服务器…

部署 Spring 项目到 Linux 云服务器上

关于 Linux 服务器安装 JDK ,Mysql&#xff0c;配置安全组&#xff08;这些都是必要的&#xff09; 推荐看在 Linux 上搭建 Java Web 项目环境&#xff08;最简单的进行搭建&#xff09; 流程 1.上传Jar包到服务器 要想部署 Spring 项目&#xff0c;先要将 Spring 项目打成 J…

【51单片机】实现一个动静态数码管显示项目(超全详解&代码&图示)(5)

前言 大家好吖&#xff0c;欢迎来到 YY 滴单片机 系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过单片机的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY…

力扣优选算法100道——【模板】前缀和(一维)

【模板】前缀和_牛客题霸_牛客网 (nowcoder.com) 目录 &#x1f6a9;了解题意 &#x1f6a9;算法原理 &#x1f388;设定下标为1开始 &#x1f388;取值的范围 &#x1f6a9;实现代码 &#x1f6a9;了解题意 第一行的3和2&#xff0c;3代表行数&#xff0c;2代表q次查询(…

SegmentAnything官网demo使用vue+python实现

一、效果&准备工作 1.效果 没啥好说的&#xff0c;低质量复刻SAM官网 https://segment-anything.com/ 需要提一点&#xff1a;所有生成embedding和mask的操作都是python后端做的&#xff0c;计算mask不是onnxruntime-web实现的&#xff0c;前端只负责了把rle编码的mask解…

C#,栅栏油漆算法(Painting Fence Algorithm)的源代码

1 刷油漆问题 给定一个有n根柱子和k种颜色的围栏&#xff0c;找出油漆围栏的方法&#xff0c;使最多两个相邻的柱子具有相同的颜色。因为答案可以是大的&#xff0c;所以返回10^97的模。 计算结果&#xff1a; 2 栅栏油漆算法的源程序 using System; namespace Legalsoft.Tr…