书接上回,我们继续来聊聊.NET9和C#13带来的新变化。

01、新的泛型约束 allows ref struct

这是在 C# 13 中,引入的一项新的泛型约束功能,允许对泛型类型参数应用 ref struct 约束。

可能这样说不够直观,简单来说就是Span、ReadOnlySpan类型,我们直接看下面的代码示例:

在没有新的约束allows ref struct之前,Span是不能当参数传入的,直接编译错误,但是有了新约束则就可以支持Span参数了。

因此C# 13 中引入了 where T : allows ref struct 泛型约束后使得我们可以对泛型参数类型进行更加精细的控制。通过这个特性,泛型方法或类就可以接受 ref struct 类型,如 Span 、ReadOnlySpan等,因为这些类型是在栈上分配内存,能够提供更高效的内存管理和更快的执行速度,所以这个新特性特别适用于高性能、内存密集型的泛型方法和类,可以有效避免堆分配和垃圾回收的开销。

02、ref struct接口

在 C# 13 之前,ref struct 是无法实现接口的。 从 C# 13 开始,ref struct可实现接口,但必须遵循 ref 安全性规则。 例如,由于需要装箱转换,因此无法将 ref struct 类型转换为接口类型。

如上图,ref struct类型可以实现IInterface接口,但是当用IInterface接口去接收RefStructInterface类型时则直接编译报错,无论直接接收还是强制转换都是不支持的。

03、在异步方法中使用ref struct

从C# 13开始,ref struct可以在异步方法中使用,但是有一个限制:它们不能在与 await 表达式同一个代码块中交互。这是为了避免 ref struct在跨越异步操作时引发内存安全问题,因为 ref struct 类型的实例通常存储在栈上,并且不能在异步操作中跨越栈帧。

下面代码是在异步方法中使用ref struct示例:

ref int Process(ref int x)
{
return ref x;
}
//在异步方法中使用ref
async Task RefInAsync()
{
var value = 0;
await Task.Delay(0);
ref var local = ref Process(ref value);
}

04、在迭代器中使用ref struct

从 C# 13 开始,允许在迭代器方法中使用 ref struct,前提是满足以下条件:不能在包含 yield return 的代码段中使用它们。这是因为yield return 语句会导致方法的执行暂停并在以后继续执行。如果在这期间使用了ref struct,可能会导致这些类型的生命周期管理出现问题(例如跨越栈帧的切换)。为了避免这种问题,C# 13 规定,如果要在迭代器方法中使用 ref struct,则不能在 yield return 语句所在的代码段中操作它们。

下面是在迭代器中使用ref struct示例代码:

ref int Process(ref int x)
{
return ref x;
}
//在迭代器中使用ref
IEnumerable<int> RefInIterator(int[] array)
{
for (var i = 0; i < array.Length; i++)
{
ref var v = ref Process(ref array[i]);
yield return v;
}
}

05、部分属性、部分索引器

早在C#2就引入了部分类,在C#3引入了部分方法,到现在C#13又新增了部分属性和部分索引器。

这一改进这意味着允许属性和索引器可以跨越多个部分进行声明和实现。这给自动生成代码或分离关注点带来了极大便利,也更加灵活地生成和管理属性代码,特别适用于与源代码生成器等工具结合使用的场景。

以下是 C# 13 中属性支持partial的示例:

public partial class PartialExamples
{
//部分属性
public partial int Capacity { get; set; }
//部分索引器
public partial string this[int index] { get; set; }
//部分方法
public partial string? TryGetItemAt(int index);
}
public partial class PartialExamples
{
private List<string> _items = ["one", "two", "three", "four", "five"];
//部分属性
public partial int Capacity
{
get => _items.Count;
set
{
if ((value != _items.Count) && (value >= 0))
{
_items.Capacity = value;
}
}
}
//部分索引器
public partial string this[int index]
{
get => _items[index];
set => _items[index] = value;
}
//部分方法
public partial string? TryGetItemAt(int index)
{
if (index < _items.Count)
{
return _items[index];
}
return null;
}
}

06、foreach 支持Index

相信很多人都遇到过想要在foreach的时候获取集合元素当前索引,一般两种选择,一种自己维护一个变量,一种直接改用for。

而.NET9开始总算改变了这一现状,可以在foreach时候同时获取到当前元素及其索引。

我们下面看看Index()方法给我们带来了多大便利,代码如下:

//.NET 9 之前
public void Loop()
{
List<string> items = ["张三", "李四", "王五"];
var idx = 0;
foreach (var item in items)
{
idx++;
Console.WriteLine($"第{idx}个人名字是:{item}");
}
}
//.NET 9
public void LoopNew()
{
List<string> items = ["张三", "李四", "王五"];
//直接获取索引、元素
foreach ((int Index, string Item) in items.Index())
{
Console.WriteLine($"第{Index + 1}个人名字是:{Item}");
}
}
//.NET 9
public void LoopNew2()
{
List<string> items = ["张三", "李四", "王五"];
//先获取元组后,再获取索引、元素
foreach (var item in items.Index())
{
Console.WriteLine($"第{item.Index + 1}个人名字是:{item.Item}");
}
}

注:测试方法代码以及示例源码都已经上传至代码库,有兴趣的可以看看。https://gitee.com/hugogoos/Planner

.NET9 - 新功能体验(二)的更多相关文章

  1. VS2017十五项新功能体验

    Visual Studio 2017十五项新功能体验 Visual Studio 2017正式已经于2017.3.7号正式发布,选在这一天发布也是为了纪念Visual Studio 二十周年.MVP ...

  2. Visual Studio 2017十五项新功能体验

    Visual Studio 2017正式已经于2017.3.7号正式发布,选在这一天发布也是为了纪念Visual Studio 二十周年.MVP 2017技术峰会将于这个周末(3.17)在北京举办,由 ...

  3. VS2015预览版中的C#6.0 新功能(二)

    VS2015预览版中的C#6.0 新功能(一) VS2015预览版中的C#6.0 新功能(三) 自动属性的增强 只读自动属性 以前自动属性必须同时提供setter和getter方法,因而只读属性只能通 ...

  4. MWeb 1.4 新功能介绍二:静态博客功能增强

    MWeb 比较有特色的是一键生成静态博客功能,然后从 MWeb 最开始规划要做静态博客生成功能时,我就希望 MWeb 的静态博客生成功能在易用的同时,还要有很强大的扩展性. 比如说能自己增加网站公告, ...

  5. 最新版Swagger 3升级指南和新功能体验!

    Swagger 3.0 发布已经有一段时间了,它于 2020.7 月 发布,但目前市面上使用的主流版本还是 Swagger 2.X 版本和少量的 1.X 版本,然而作为一名合格的程序员怎么能不折腾新技 ...

  6. VS2015预览版中的C#6.0 新功能(三)

    VS2015预览版中的C#6.0 新功能(一) VS2015预览版中的C#6.0 新功能(二) Using static 使用using StaticClass,你可以访问StaticClass类里的 ...

  7. VS2015预览版中的C#6.0 新功能(一)

    VS2015预览版中的C#6.0 新功能(二) VS2015预览版中的C#6.0 新功能(三) VS2015的预览版在11月12日发布了,下面让我们来看看C#都提供了哪些新的功能. 字符串添写(Str ...

  8. CRM 2013 系统设置新功能二:Entity images 图像字段

    CRM2013系统默认的许多实体都已经有了图像的选择,如 右上角可以设置当前用户的头像. 客户.联系人等都可以,下面将介绍一下此项新功能: 一.实体中新建图像字段,其中系统自动命名entityinag ...

  9. 个人官网第8次升级(新功能、用户体验、修复bug、系统优化)

    1.新功能. 操作日志和搜索日志的Excel报表下载. 2.用户体验. 如果是通过搜索,进入到一篇内容, 搜索关键词需要高亮. 比如,搜索"程序员"出现若干内容链接,打开链接的页面 ...

  10. 地图SDK全面升级 – 数十项新功能及优化等你来体验

    腾讯位置服务地图SDK是一套提供多种地理位置服务的应用程序接口.通过调用该接口,开发者可以在自己的应用中加入地图相关的功能(如地图展示.标注.绘制图形等),轻松访问腾讯地图服务和数据,构建功能丰富.交 ...

随机推荐

  1. man 切换颜色配置

    man 命令显示的命令手册默认是没有颜色的.为了使 man 命令的输出更为生动,可以使用如下两种方法修改 man 命令的颜色配置. 方法一:设置环境变量 在你的 .zshrc / .bashrc 中添 ...

  2. VMware Workstation Pro 开启虚拟化引擎

    摘要:想开启 VMware Workstation Pro 虚拟机上的 虚拟化 Intel VT-x/EPT 或 AMD-V/RVI 选项,却发现打不开.在网上一番搜集之后找到了解决办法. ️ 注意: ...

  3. Java Swing Loading转圈的进度提示框

    Java Swing Loading转圈的进度提示框 具体只需要两个类 AnimatedPanel.java InfiniteProgressPanel.java 前因:我们开发的web应用,有个奇葩 ...

  4. 根据Uri,Cursor没有获取到对应的属性

    Android: 背景:调用摄像头,拍摄视频,指定保存的地址,但是返回的Cursor文件,只有名称和大小的属性,没有其他诸如时长,连ID属性都没有 使用 cursor.getInt(cursor.ge ...

  5. 使用js闭包实现可取消的axios请求

    在平常开发中,经常会遇到重复请求的情况,也许是因为网络问题,也许是因为接口问题等等,传统做法是客户端采用防抖来限制用户发送接口的频率,一般出个loading转圈圈的形式, 但是很少使用取消请求的做法, ...

  6. Razor 常用又容易忘记语法

    1. <text> 要写 text 可以用这个特殊 element @:&nbsp   @: 也是一个可以写 text 的方式 2. @Html.Raw($@"<s ...

  7. manim边学边做--弧形多边形

    弧形多边形是一种结合了圆弧和多边形的图形,这类几何图形在设计中应用非常广泛. 比如在家居设计中,看看家里的沙发,餐桌和座椅等,它们的边角,靠背等地方都是弧形的设计,这种设计有效柔化了室内空间,使整体氛 ...

  8. 30. 串联所有单词的子串 Golang实现

    题目描述: 给定一个字符串 s 和一个字符串数组 words. words 中所有字符串 长度相同 . s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串. 例如, ...

  9. [OI] 交互 | pipe

    关于如何在本地实现交互 管道 Linux 内置了一种管道操作,可以方便地把 \(A\) 程序的输出和 \(B\) 程序的输入连接起来,只需要以下指令: A | B 此代码行的意思是:同时运行 \(A\ ...

  10. Dockerfile构建镜像(八)

    一.构建镜像 现在让我们再回到之前定制的 nginx 镜像的 Dockerfile 来.现在我们明白了这个 Dockerfile 的内容,那么让我们来构建这个镜像吧.在 Dockerfile 文件所在 ...