.NET9 - 新功能体验(三)
书接上回,我们继续来聊聊.NET9和C#13带来的新变化。

01、Linq新方法 CountBy 和 AggregateBy
引入了新的方法 CountBy 和 AggregateBy后,可以在不经过GroupBy 分配中间分组的情况下快速完成复杂的聚合操作,同时方法命名也非常直观,可以大大提升工作效率。
我们先以CountBy为例,简单实现一个小功能,统计不同年龄有多少人,代码如下:
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
}
public void CountByExample()
{
var students = new List<Student>
{
new Student { Name = "小明", Age = 10 },
new Student { Name = "小红", Age = 12 },
new Student { Name = "小华", Age = 10 },
new Student { Name = "小亮", Age = 11 }
};
//统计不同年龄有多少人,两个版本实现
//.NET 9 之前
var group = students.GroupBy(x => x.Age);
foreach (var item in group)
{
Console.WriteLine($"年龄为:{item.Key},有:{item.Count()} 人。");
}
//.NET 9
foreach (var student in students.CountBy(c => c.Age))
{
Console.WriteLine($"年龄为:{student.Key},有:{student.Value} 人。");
}
}
通过代码可以发现,老版本中必须先调用GroupBy分组再调用Count统计才可完成,而现在只需要调用CountBy即可。
我们再以AggregateBy为例子,看看新老版本中如何计算每个班级中各自学生总年龄,代码如下:
public class Student
{
public string Name { get; set; }
public string Grade { get; set; }
public int Age { get; set; }
}
public void AggregateByExample()
{
var students = new List<Student>
{
new Student { Name = "小明", Grade = "一班", Age = 10 },
new Student { Name = "小红", Grade = "二班", Age = 12 },
new Student { Name = "小华", Grade = "一班", Age = 10 },
new Student { Name = "小亮", Grade = "二班", Age = 11 }
};
//统计每个班级各自学生总年龄,两个版本实现
//.NET 9 之前
var old = students
.GroupBy(stu => stu.Grade)
.ToDictionary(group => group.Key, group => group.Sum(stu => stu.Age))
.AsEnumerable();
foreach (var item in old)
{
Console.WriteLine($"班级:{item.Key},总年龄:{item.Value} 。");
}
//.NET 9
foreach (var group in students.AggregateBy(c => c.Grade, 0, (acc, stu) => acc + stu.Age))
{
Console.WriteLine($"班级:{group.Key},总年龄:{group.Value} 。");
}
}
02、序列化加强
在System.Text.Json中,.NET 9为序列化提供了新的选项和一个新的单例。
1、缩进选项
现在可以通过JsonSerializerOptions新属性IndentCharacter和IndentSize,自定义写入 JSON 的缩进字符和缩进大小。看看下面代码。
static void Main()
{
var options = new JsonSerializerOptions
{
WriteIndented = true,
IndentCharacter = '\t',
IndentSize = 2,
//处理中文乱码
Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
};
var json = JsonSerializer.Serialize(
new Student { Name = "小明", Grade = "一班", Age = 10 },
options
);
Console.WriteLine(json);
Console.ReadKey();
}
代码执行效果如下:

2、默认 Web 选项单例
在之前的版本中如果想要以小驼峰命名规则序列化对象可以配合JsonProperty特性实现。现在则可以直接通过JsonSerializerOptions.Web单例直接实现。
var json = JsonSerializer.Serialize(
new Student { Name = "xiaoming", Grade = "yinianji", Age = 10 },
JsonSerializerOptions.Web
);
Console.WriteLine(json);
代码执行效果如下:

03、Task新方法Task.WhenEach
在.NET9之前,如果我们有一个任务列表,并希望每个任务完成后立刻处理它,那么我们只能通过不停的调用Task.WaitAny()方法来实现,现在.NET9引入了Task.WhenEach方法,以一种更优雅、更高效的方式处理这种情况。
因为Task.WhenEach 返回 IAsyncEnumerable<Task>,因此可以配合await foreach语句在任务完成时对其进行迭代,下面我们一起看看示例。
async Task WhenEachAsync()
{
//生成100个随机时间完成的任务列表
var tasks = Enumerable.Range(1, 100)
.Select(async i =>
{
await Task.Delay(new Random().Next(1000, 5000));
return $"任务 {i} 完成";
})
.ToList();
//.NET 9 之前
while (tasks.Count > 0)
{
var completedTask = await Task.WhenAny(tasks);
tasks.Remove(completedTask);
Console.WriteLine(await completedTask);
}
//.NET 9
await foreach (var completedTask in Task.WhenEach(tasks))
{
Console.WriteLine(await completedTask);
}
}
04、新的 TimeSpan.From* 重载
在.NET9之前TimeSpan类提供了几种From*方法,可以使用double类型来创建TimeSpan对象。但是,由于double是基于二进制的浮点格式,因此固有的不精确性可能会导致错误。

为了解决这个问题,.NET 9 添加了新的重载方法,可以使用整数创建TimeSpan对象。

如下面这段代码:
TimeSpan timeSpan1 = TimeSpan.FromSeconds(value: 101.832);
Console.WriteLine($"timeSpan1 = {timeSpan1}");
// timeSpan1 = 00:01:41.8319999
TimeSpan timeSpan2 = TimeSpan.FromSeconds(seconds: 101, milliseconds: 832);
Console.WriteLine($"timeSpan2 = {timeSpan2}");
// timeSpan2 = 00:01:41.8320000
05、新的内置Swagger
从.NET9开始使用Scalar代替内置的Swagger(Swashbuckle),一方面是因为Swashbuckle项目维护不够积极,另一个方面也是内部希望更专业于OpenAPI的发展。不管原因如何,我们都要根据自己的情况做好选择。
下面我们来一起体验一下Scalar。
首先创建一个Web Api项目,然后安装Scalar.AspNetCore包,修改Prag代码如:
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddOpenApi();
var app = builder.Build();
// scalar/v1
app.MapScalarApiReference();
app.MapOpenApi();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
然后我们添加一个简单的控制器,添加增删改查四个方法,代码如下:
[ApiController]
[Route("[controller]")]
public class OrdersController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<OrdersController> _logger;
public OrdersController(ILogger<OrdersController> logger)
{
_logger = logger;
}
[HttpGet(Name = "")]
public IEnumerable<Order> Get()
{
return Enumerable.Range(1, 5).Select(index => new Order
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Price = Random.Shared.Next(-20, 55),
Name = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
[HttpPost(Name = "")]
public bool Post(Order order)
{
return true;
}
[HttpPut(Name = "{id}")]
public bool Put(string id, Order order)
{
return true;
}
[HttpDelete(Name = "{id}")]
public bool Delete(string id)
{
return true;
}
}
然后我们允许代码看看效果:


卖相还是相当惊艳的,左侧是接口列表,左下角可以切换黑白两种风格主题,右侧是接口详情,同时还配备了多种语言请求格式。
我们点击右下角Test Request测试一下获取接口。

可以在左边填写好参数,添加最上面的Send,会看到右下角请求结果。更详细复杂的应用大家可以自己摸索摸索。
注:测试方法代码以及示例源码都已经上传至代码库,有兴趣的可以看看。https://gitee.com/hugogoos/Planner
.NET9 - 新功能体验(三)的更多相关文章
- VS2017十五项新功能体验
Visual Studio 2017十五项新功能体验 Visual Studio 2017正式已经于2017.3.7号正式发布,选在这一天发布也是为了纪念Visual Studio 二十周年.MVP ...
- VS2015预览版中的C#6.0 新功能(三)
VS2015预览版中的C#6.0 新功能(一) VS2015预览版中的C#6.0 新功能(二) Using static 使用using StaticClass,你可以访问StaticClass类里的 ...
- Visual Studio 2017十五项新功能体验
Visual Studio 2017正式已经于2017.3.7号正式发布,选在这一天发布也是为了纪念Visual Studio 二十周年.MVP 2017技术峰会将于这个周末(3.17)在北京举办,由 ...
- 最新版Swagger 3升级指南和新功能体验!
Swagger 3.0 发布已经有一段时间了,它于 2020.7 月 发布,但目前市面上使用的主流版本还是 Swagger 2.X 版本和少量的 1.X 版本,然而作为一名合格的程序员怎么能不折腾新技 ...
- VS2015预览版中的C#6.0 新功能(二)
VS2015预览版中的C#6.0 新功能(一) VS2015预览版中的C#6.0 新功能(三) 自动属性的增强 只读自动属性 以前自动属性必须同时提供setter和getter方法,因而只读属性只能通 ...
- VS2015预览版中的C#6.0 新功能(一)
VS2015预览版中的C#6.0 新功能(二) VS2015预览版中的C#6.0 新功能(三) VS2015的预览版在11月12日发布了,下面让我们来看看C#都提供了哪些新的功能. 字符串添写(Str ...
- SharePoint 2013的100个新功能之网站管理(三)
一:跨网站发布 跨网站发布是SharePoint 2013的一个新功能,可以使用户跨网站集.Web应用程序甚至是场重用内容.该功能叫做跨网站发布功能.用户可以使用该功能在SharePoint 2013 ...
- JPA2.1 中三个提升应用性能的新功能
经常在网上看到开发者们抱怨 JPA 性能低下的帖子或文章,但如果仔细查看这些性能问题,常会发现导致问题的根本原因大致包括以下几个: 使用过多的 SQL 查询从数据库中获取所需的实体信息,即我们常说的n ...
- arduino新入手体验:三个小实验
新入手体验:三个小实验 一:一个LED闪烁 控制要求:1个LED灯,每隔50ms闪烁一次 实物连接图: 控制代码: //2018.6/11 ;//定义数字接口10,对应 void setup() { ...
- SharePoint 2013的100个新功能之内容管理(三)
一:视频中的人 作为视频内容类型的一部分,一个新的栏"视频中的人"被加入到其中,可以指定视频中的人,作为视频的元数据.当你编辑视频属性时可以查看到该栏.更多信息 二:重建索引 一个 ...
随机推荐
- 【FFmpeg】之Mac系统爬取所有M3U8视频下载方法
前言 由于有的网站不允许下载视频,到了有效期就不能看了,但是我想以后反复看,怎么办呢? 前提准备 操作系统:Mac 浏览器:谷歌浏览器 抓取m3u8工具:猫爪 视频处理工具:ffmpeg 需要安装工具 ...
- android 播放视频页面黑屏,且报错:Couldn't open 'xxxxxx' java.io.FileNotFoundException: No content provider:
原因为,activity的顶部布局,VideoView设定了android:background="@color/bg_black"去掉就可以了 之前跑着都正常,改了UI后就没有去 ...
- fluent python-chap2
1. 内置序列类型 容器序列: list tuple collections.deque 可以存放不同类型的数据. 存放的是它们所包含的任意类型的对象的引用. 扁平序列: str bytes byte ...
- 合合信息亮相新加坡科技周——Big Data & AI World Expo展示AI驱动文档数字化的前沿能力
合合信息亮相新加坡科技周--Big Data & AI World Expo展示AI驱动文档数字化的前沿能力 展会规模背景: 2023年10月11日-12日,合合信息在TECH WEEK ...
- CPRFL:基于CLIP的新方案,破解长尾多标签分类难题 | ACM MM'24
现实世界的数据通常表现为长尾分布,常跨越多个类别.这种复杂性突显了内容理解的挑战,特别是在需要长尾多标签图像分类(LTMLC)的场景中.在这些情况下,不平衡的数据分布和多物体识别构成了重大障碍.为了解 ...
- Vue3——Pinia+Pinia持久化
Pinia 安装 Pinia npm install pinia 创建一个 pinia 实例 (根 store) 并将其传递给应用 // store/index.ts // 仓库大仓库 import ...
- python3 numpy的一些小知识点
简介 一个用python实现的科学计算,包括: 1.一个强大的N维数组对象Array: 2.比较成熟的(广播)函数库: 3.用于整合C/C++和Fortran代码的工具包: 4.实用的线性代数.傅里叶 ...
- 基于腾讯云短信接口和nodejs服务器实现手机号验证码
知识储备:js基础.nodejs基础.ajax基础: 1. 手机验证码原理 表单提交,把手机号码传送到后端:后端拿到手机号码后根据相关算法随机形成一个验证码,并将其保存在数据库:用户拿到验证码后将验证 ...
- Android复习(三)清单文件中的元素——>action、activity-alias、category、compatible-screens、data
<action> 语法: <action android:name="string" /> 包含于: <intent-filter> 说明: ...
- Python 潮流周刊#72:Python 3.13.0 最终版已发布!(摘要)
本周刊由 Python猫 出品,精心筛选国内外的 250+ 信息源,为你挑选最值得分享的文章.教程.开源项目.软件工具.播客和视频.热门话题等内容.愿景:帮助所有读者精进 Python 技术,并增长职 ...