书接上回,我们继续来聊聊.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 - 新功能体验(三)的更多相关文章

  1. VS2017十五项新功能体验

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

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

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

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

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

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

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

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

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

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

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

  7. SharePoint 2013的100个新功能之网站管理(三)

    一:跨网站发布 跨网站发布是SharePoint 2013的一个新功能,可以使用户跨网站集.Web应用程序甚至是场重用内容.该功能叫做跨网站发布功能.用户可以使用该功能在SharePoint 2013 ...

  8. JPA2.1 中三个提升应用性能的新功能

    经常在网上看到开发者们抱怨 JPA 性能低下的帖子或文章,但如果仔细查看这些性能问题,常会发现导致问题的根本原因大致包括以下几个: 使用过多的 SQL 查询从数据库中获取所需的实体信息,即我们常说的n ...

  9. arduino新入手体验:三个小实验

    新入手体验:三个小实验 一:一个LED闪烁 控制要求:1个LED灯,每隔50ms闪烁一次 实物连接图: 控制代码: //2018.6/11 ;//定义数字接口10,对应 void setup() { ...

  10. SharePoint 2013的100个新功能之内容管理(三)

    一:视频中的人 作为视频内容类型的一部分,一个新的栏"视频中的人"被加入到其中,可以指定视频中的人,作为视频的元数据.当你编辑视频属性时可以查看到该栏.更多信息 二:重建索引 一个 ...

随机推荐

  1. 2023/11/16 NOIP 模拟赛

    T1 基于1的算术 标签 暴力枚举 思路1 赛时想了个假的 DP,只拿了 77 分,,, 小于 \(10^{15}\) 的仅由 \(1\) 组成的数只有 \(15\) 个,直接枚举即可. 想了一个做法 ...

  2. 18 Python如何操作文件?

    本篇是 Python 系列教程第 18 篇,更多内容敬请访问我的 Python 合集 1 打开文件 通常使用内置的 open(文件路径, 模式, encoding="utf-8") ...

  3. Coze插件发布!PDF转Markdown功能便捷集成,打造你的专属智能体

    近日,TextIn开发的PDF转Markdown插件正式上架Coze平台. 在扣子搜索"pdf转markdown",或在Coze平台搜索"pdf2markdown&quo ...

  4. 痛定思痛,好好做人,从头过一遍PyTorch框架(一)(1.深度学习简介、2.预备知识)

    现在是2024年2月24日,13:59,从研一就开始断断续续说要过一遍框架,到现在博一下学期,还一直拖着呢,拖延症太可怕啦,决定好好做人,不拖了,就从现在开始,好好过一遍,呜呜呜呜呜呜呜呜,(罪该万死 ...

  5. TypeScript – Using Disposable

    前言 TypeScript v5.2 多了一个新功能叫 Disposable. Dispose 的作用是让 "对象" 离开 "作用域" 后做出一些 " ...

  6. MDC – Material Design, Angular Material, MDC, MWC, Lit 的关系

    前言 它们关系挺乱的, 而且不只是我一个人感觉乱 还有 所以这篇做一个整理吧. Material Design Google 的设计指南. 早年用于 Android Apps, 现在也用于 Web A ...

  7. HTML & CSS – Responsive Image 响应式图片 (完整版)

    前言 之前就有写过关于 Retina 和 Responsive Image 响应式图片 (responsive image) Retina 显示屏 但写的太烂了, 所以有了后来的 屏幕, 打印, 分辨 ...

  8. LinerProgression

    手动实现线性回归 点击查看代码 import torch import pandas as pd import numpy as np import matplotlib.pyplot as plt ...

  9. docker 安装 elasticsearch 集群

    此处部署为单个服务器启动三个elasticsearch容器 问题:本打算在三个服务器上单独部署elasticsearch 容器,elasticsearch.yml 注册用的宿主机ip,但是容器之间通信 ...

  10. 【赵渝强老师】Oracle数据库的内存结构

    首先,我们通过一张图片来了解一下Oracle数据库的内存结构,如下: 每个数据库实例有两个关联的内存结构-系统全局区(SGA),程序全局区(PGA). 系统全局(SGA):一组共享的内存结构(称为SG ...