Skip to content

Commit 1252a29

Browse files
committed
publish episode 67
1 parent 5941738 commit 1252a29

File tree

2 files changed

+352
-1
lines changed

2 files changed

+352
-1
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616

1717
### 2025
1818

19+
**五月份** : [第 067 期](docs/episode-067.md) :high_brightness:
20+
1921
**四月份** : [第 066 期](docs/episode-066.md)
2022

21-
**三月份** : [第 065 期](docs/episode-065.md) :high_brightness:
23+
**三月份** : [第 065 期](docs/episode-065.md)
2224

2325
**一月份** : [第 064 期](docs/episode-064.md)
2426

docs/episode-067.md

Lines changed: 349 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,349 @@
1+
# .NET 每周分享第 67 期
2+
3+
## 卷首语
4+
5+
社区人员发现,在某些 .NET 官方文档页面中,出现了关于使用 GitHub Copilot 的提示,例如:[自定义属性名称和顺序](https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/customize-properties#use-github-copilot-to-customize-property-names-and-order), [使用 Copilot 进行单元测试](https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-with-copilot)。 他们认为,这些提示可能被视为对 GitHub Copilot 的推广,尤其是在 .NET Foundation 自称为“独立、非营利组织”的背景下。他质疑:如果文档中推广第三方工具(即使是免费的),是否违背了其独立性的承诺?此外,Copilot 并非完全免费,用户可能需要以数据和隐私为代价。他还指出,如果要保持中立,是否也应该在文档中提及其他类似工具?
6+
7+
## 行业资讯
8+
9+
1、[Microsoft Build 2025](https://devblogs.microsoft.com/dotnet/join-us-at-build-2025/)
10+
11+
![Image](https://github.com/user-attachments/assets/291895a3-03c5-4128-b8c0-f541e21771e3)
12+
13+
Microsoft Build 2025 将于 5 月 19 日至 22 日在西雅图及线上举行,面向全球开发者开放。.NET 与 C# 团队将带来超过 75 场精彩内容,涵盖 AI、云计算、应用现代化等主题。
14+
15+
重点议程包括:
16+
17+
- .NET Aspire 与 AI 集成:探索 .NET Aspire 9.3 的新特性,展示如何结合 AI 构建智能应用。
18+
- GitHub Copilot 助力应用现代化:介绍如何使用 Copilot 升级 .NET 应用,实现自动修复与依赖分析。
19+
- Hanselman 与 Toub 的实战演示:两位专家现场调试代码,深入讲解 .NET 性能优化技巧。
20+
- Python 与 .NET 融合:展示如何将 Python 的数据科学能力与 .NET 的企业级开发结合,构建 AI 解决方案。
21+
22+
无论您是经验丰富的开发者,还是初学者,都能在本次大会中收获丰富的知识与实践经验。欢迎通过线上或线下方式参与,与全球开发者共同交流学习。
23+
24+
## 文章推荐
25+
26+
1、[使用反射的四种场景](https://blog.elmah.io/4-real-life-examples-of-using-reflection-in-c/)
27+
28+
反射是 C# 的一项运行时功能,允许程序动态地检查和操作程序集、类型(如类、接口、值类型)、方法、字段和属性的元数据。通过 System.Reflection 命名空间,开发者可以在运行时创建对象实例、调用方法以及加载程序集。
29+
30+
反射适用于以下场景:
31+
32+
- 需要根据外部输入在运行时加载程序集或类型。
33+
- 处理结构未知的 JSON 或 XML 序列化。
34+
- 自动将具有相同名称或属性的属性之间的数据进行映射。
35+
- 开发依赖注入(DI)容器以解析构造函数、注入参数并激活服务。
36+
- 导出数据到 CSV 时,手动映射大量类型的属性不切实际。
37+
- 测试工具(如 NUnit 或 xUnit)使用反射发现测试方法和属性,而无需手动注册每个测试用例。
38+
- 避免为重复的类型方法和属性编写样板代码。反射可以帮助自动访问属性或调用方法。
39+
- 动态访问和验证模型属性。
40+
41+
常见的方法有
42+
43+
1. 方法的调用
44+
2. 动态 CSV/JSON 的导出
45+
3. 自定义类型之间的转换映射
46+
4. 动态插件/程序集加载
47+
48+
虽然反射功能强大,但会带来性能开销。应遵循以下最佳实践:
49+
50+
- 避免在紧密循环中使用反射。
51+
- 在性能关键的代码中,避免使用反射。
52+
- 重复调用 `GetMethod()``GetProperty()` 可能代价高昂。使用缓存来存储反射结果。
53+
- 使用编译的委托或表达式树来避免重复反射。这可以显著加快性能关键路径中的属性访问或方法调用:
54+
55+
2、[在 System.Text.Json 中使用 Source Generation](https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/source-generation)
56+
57+
`System.Text.Json` 的源生成功能(Source Generation)自 .NET 6 起引入,旨在提升 JSON 序列化与反序列化的性能,减少运行时反射的开销。
58+
59+
使用步骤如下:
60+
61+
- 创建一个继承自 `JsonSerializerContext` 的部分类。
62+
- 在该类上应用 `[JsonSerializable]` 特性,指定需要序列化或反序列化的类型。
63+
- 在代码中使用 `JsonSerializer` 的方法,并传入生成的上下文实例或类型信息。
64+
65+
3、[C# 中的模式匹配](https://www.arungudelli.com/csharp-tips/pattern-matching-in-csharp/)
66+
67+
模式匹配是一种机制,允许你将输入值与模式进行比较,并在匹配时执行相应操作。在 C# 中,模式匹配可用于以下结构:
68+
69+
- is 表达式
70+
- switch 语句
71+
- switch 表达式
72+
73+
主要使用类型有如下表格
74+
75+
模式类型 | 最佳使用场景
76+
-- | --
77+
声明/类型 | 类型检查和转换
78+
常量 | 精确值匹配
79+
关系 | 范围比较
80+
逻辑 | 复杂组合
81+
属性 | 匹配对象的属性值
82+
位置 | 基于解构的匹配
83+
var | 通用值提取
84+
丢弃 | 匹配任何内容,忽略值
85+
列表 | 匹配数组/列表及子序列
86+
87+
根据作者的经验,模式匹配在以下情况下表现出色:
88+
89+
- 处理异构类型(例如 object 参数)时
90+
- 避免冗长的空值检查。
91+
- 使条件语句更具可读性。
92+
- 处理复杂的分支逻辑(例如转换 API 响应)时。
93+
94+
4、[Azure Function 构建 MCP Remote Server](https://devblogs.microsoft.com/dotnet/build-mcp-remote-servers-with-azure-functions/)
95+
96+
本文介绍了如何利用 [Azure Functions](https://learn.microsoft.com/azure/azure-functions/) 构建一个MCP远程服务器,用于处理来自远程设备的请求。它强调了以下关键点:
97+
98+
**背景**
99+
100+
- 某些场景需要与远程设备(如物联网设备)通信。
101+
- 这些设备可能不支持现代协议(如 HTTPS 或 gRPC),需要简化的接口。
102+
- Azure Functions 是构建轻量级、事件驱动的后端服务的理想选择。
103+
104+
**架构概述**
105+
106+
- 使用 Azure Functions 提供一个 HTTP 端点,供远程客户端请求。
107+
- 结合 Azure Durable Entities 管理设备状态和指令执行。
108+
- 结合 Azure Storage 实现数据持久化。
109+
110+
**示例实现**
111+
112+
- 提供了基于 .NET 的函数模板,包括:
113+
- `DeviceCommandFunction`: 接收和处理设备命令。
114+
- `DeviceStateEntity`: 保存设备状态。
115+
- `DurableEntityClient`: 调用实体以管理设备状态。
116+
117+
**优势**
118+
119+
- 减少基础设施负担:无需管理服务器。
120+
- 易于扩展:可自动扩容应对大量设备。
121+
- 成本高效:使用按需计费的无服务器架构。
122+
123+
结论
124+
Azure Functions 是构建简洁、高效、可扩展的 MCP 远程服务器的理想工具,适用于各种边缘计算或远程设备通信场景。
125+
126+
5、[使用向量化加速 C# 性能](https://btburnett.com/csharp/2024/12/09/using-vectorization-in-csharp-to-boost-performance)
127+
128+
SIMD(单指令多数据)是一种并行处理技术,允许 CPU 在一个指令周期内处理多个数据项。在 .NET 中,SIMD 通过 Vector<T> 类型实现,例如 `Vector128<T>``Vector256<T>` 等,这些类型根据 CPU 的支持情况提供不同大小的向量操作。
129+
例如,使用传统方法对整数数组求和:
130+
131+
```csharp
132+
public int Sum(ReadOnlySpan<int> values)
133+
{
134+
int accumulator = 0;
135+
foreach (var i in values)
136+
{
137+
accumulator += i;
138+
}
139+
return accumulator;
140+
}
141+
```
142+
在一次即兴的 SIMD 教学中,作者查看了 .NET 源代码中 Sum 方法的实现,发现它并未使用向量化:
143+
144+
```csharp
145+
private static TResult Sum<T, TResult>(ReadOnlySpan<T> span)
146+
where T : struct, INumber<T>
147+
where TResult : struct, INumber<TResult>
148+
{
149+
TResult sum = TResult.Zero;
150+
foreach (T value in span)
151+
{
152+
checked { sum += TResult.CreateChecked(value); }
153+
}
154+
return sum;
155+
}
156+
```
157+
这让作者认为有机会通过向量化来优化该方法。作者编写了使用 `Vector<T>` 的向量化版本,并在性能测试中取得了数量级的提升。然而,他意识到原始方法使用了 checked 关键字来进行溢出检查,而 SIMD 加法操作默认忽略溢出,因此新方法在功能上并不等价。
158+
为了在向量化的同时保留溢出检测,作者研究了二进制补码的原理,并使用位操作来检测溢出:
159+
160+
```csharp
161+
int sum = x + y;
162+
bool isOverflow = (sum ^ x) & (sum ^ y) & int.MinValue != 0;
163+
```
164+
165+
作者的优化被合并到了 .NET 8 中,并在 Stephen Toub 的年度性能改进博客中提及。对于 1024 个 32 位整数的求和操作,性能从 .NET 7 的 347.28 纳秒提升到了 .NET 8 的 78.26 纳秒,提升了约 77%。
166+
167+
6、[构建 Web API 常见的 5 类错误](https://stefandjokic.tech/posts/building-apis-top-5-mistakes)
168+
169+
构建 Web API 看似简单,实则复杂。本文总结了开发者在构建 API 时常犯的五个错误,并提供了相应的解决方案,旨在帮助开发者构建更健壮、可维护的 API。
170+
171+
错误一:不校验输入
172+
开发者总是信任用户的输入,这样会导致程序崩溃或者安全漏洞
173+
解决办法:
174+
175+
- null 或者空字段校验
176+
- 格式认证
177+
- 业务逻辑认证
178+
179+
错误二:忽视版本控制
180+
许多开发者在设计 API 时未考虑版本控制,导致后续更新难以兼容旧客户端。
181+
解决方案:
182+
183+
- 在 URL 或请求头中明确指定 API 版本,例如 /api/v1/。
184+
185+
186+
错误三:错误的状态码使用
187+
返回不准确的 HTTP 状态码会导致客户端误解响应结果。
188+
解决方案:
189+
正确使用 2xx、4xx、5xx 等状态码,例如:
190+
191+
- 200 OK:请求成功。
192+
- 400 Bad Request:请求参数错误。
193+
- 401 Unauthorized:未授权访问。
194+
- 404 Not Found:资源不存在。
195+
- 500 Internal Server Error:服务器内部错误。
196+
确保错误响应中包含详细的错误信息,便于客户端调试。
197+
198+
错误四:复杂的返回类型
199+
将数据库中的实体对象返回给请求,会导致数据库结构泄露,暴露敏感字段,导致返回请求的 body 过大
200+
解决办法
201+
202+
- 返回数据库对象的的子集和必要字段
203+
204+
错误五:没有中心化的错误处理方式
205+
每个 API 处理逻辑自己定义了错误逻辑,导致非常混乱。
206+
解决方案:
207+
208+
- 使用全局错误处理中间件
209+
210+
## 视频推荐
211+
212+
1、[Null 对象的最新语法](https://www.youtube.com/watch?v=HMSfIkYI5ls&ab_channel=NickChapsas)
213+
214+
C# 的 nullable reference 类型有了新的语法,之前 `T?` 类型只能获取值的方式,而不能进行赋值,举例而言
215+
216+
```csharp
217+
class Student
218+
{
219+
public string Name { get; set; }
220+
public int Age { get; set; }
221+
}
222+
Student? student = null;
223+
Console.WriteLine(student?.Name)
224+
```
225+
226+
但是如果我们想要更新 `student` 对象的时候,需要通过这种方式进行判断
227+
228+
```csharp
229+
if (student != null)
230+
{
231+
student.Age = age;
232+
}
233+
```
234+
235+
现在新的语法 (preview 阶段) 的可以省略 `null` 判断
236+
237+
```csharp
238+
student?.Age = age;
239+
```
240+
241+
2、[如何不用dockerfile容器化一个.NET 应用程序](https://www.youtube.com/watch?v=PtGTU7thBuY)
242+
243+
🎯 视频概述
244+
本视频介绍了如何在不编写 Dockerfile 的情况下,将 .NET 应用容器化。Julio Casal 通过演示,展示了使用 .NET CLI 工具和内置功能,简化容器化流程,适用于希望快速部署 .NET 应用的开发者。
245+
246+
🧰 主要内容
247+
248+
1. 使用 .NET CLI 进行容器化
249+
介绍了如何使用 dotnet publish 命令与相关参数,生成容器镜像,无需手动编写 Dockerfile。
250+
2. 配置容器参数
251+
演示了如何通过项目文件(.csproj)或命令行参数,设置容器的基础镜像、端口等配置。
252+
3. 多平台支持
253+
讨论了如何构建支持多平台的容器镜像,确保应用在不同环境中的兼容性。
254+
4. 部署与运行
255+
展示了如何将生成的容器镜像部署到本地或云端环境,并运行 .NET 应用
256+
257+
✅ 优点
258+
259+
- 简化了容器化流程,降低了入门门槛。
260+
- 减少了对 Dockerfile 的依赖,适合快速开发和测试。
261+
- 利用 .NET CLI 工具,提升了开发效率。
262+
263+
⚠️ 注意事项
264+
265+
- 对于需要复杂配置的生产环境,仍建议使用自定义的 Dockerfile。
266+
- 了解生成的容器镜像的结构和配置,有助于更好地调试和优化。
267+
268+
3、[param 参数支持 Span](https://www.youtube.com/watch?v=xqk_ZabcM1M&ab_channel=NickChapsas)
269+
270+
C# 支持 `param` `参数修饰符,用来表示可变长度参数,这样在调用方法的时候,可以无需构造数组,直接挨个传入对象即可。但是我们知道这个一个语法糖,编译器会在方法调用之前构造一个数组,然后将数组参数传入。
271+
这样就会导致显而易见的问题,就是出现了堆内存分配的问题,如果对于性能敏感的路径,可以选择使用 `Span<T>` 而不是 `T[]` 作为参数类型,可以避免内存分配
272+
273+
```csharp
274+
[MemoryDiagnoser]
275+
public class ParamBenchmarks
276+
{
277+
private static void UseParamArray(params string[] paramArray)
278+
{
279+
foreach (var item in paramArray)
280+
{
281+
}
282+
}
283+
284+
private static void UseParamsSapn(params Span<string> paramArray)
285+
{
286+
foreach (var item in paramArray)
287+
{
288+
}
289+
}
290+
291+
[Benchmark]
292+
public void TestParamArray()
293+
{
294+
UseParamArray("Hello", "World");
295+
}
296+
297+
[Benchmark]
298+
public void TestParamsSpan()
299+
{
300+
UseParamsSapn("Hello", "World");
301+
}
302+
}
303+
```
304+
305+
结果如下
306+
307+
| Method | Mean | Error | StdDev | Median | Gen0 | Allocated |
308+
|--------------- |---------:|----------:|----------:|---------:|-------:|----------:|
309+
| TestParamArray | 3.315 ns | 0.0928 ns | 0.2736 ns | 3.188 ns | 0.0048 | 40 B |
310+
| TestParamsSpan | 1.360 ns | 0.0072 ns | 0.0060 ns | 1.357 ns | - | - |
311+
312+
4、[为项目选择最佳.NET UI框架](https://www.youtube.com/watch?v=jIVzKKi0414)
313+
314+
![Image](https://github.com/user-attachments/assets/d6d71cc4-ab62-4d34-9563-370e706d4930)
315+
316+
该视频由 .NET Foundation 发布,主题为“为你的项目选择最佳的 .NET UI 框架”。视频深入探讨了多种 .NET 用户界面框架的特点、适用场景和选择建议,帮助开发者根据项目需求做出明智决策。
317+
视频内容概览:
318+
319+
1. 主要 .NET UI 框架介绍:
320+
- Windows Forms:适用于传统桌面应用,开发简单,适合快速原型设计。
321+
- WPF(Windows Presentation Foundation):支持丰富的用户界面和数据绑定,适合需要复杂界面的桌面应用。
322+
- UWP(Universal Windows Platform):面向 Windows 10 及以上平台,支持多设备协同。
323+
- MAUI(.NET Multi-platform App UI):.NET 6 推出的跨平台框架,支持 iOS、Android、Windows 和 macOS。
324+
- Blazor:基于 Web 的 UI 框架,支持 WebAssembly 和服务器端渲染,适合构建现代 Web 应用。
325+
2. 框架对比与选择建议:
326+
- 平台支持:根据目标平台选择合适的框架,例如 MAUI 适合跨平台需求,WPF 适合 Windows 桌面应用。
327+
- 开发体验:考虑开发工具、社区支持和学习曲线,选择最适合团队的框架。
328+
- 性能与功能:评估框架的性能表现和提供的功能特性,确保满足项目需求。
329+
3. 实际案例分析:
330+
视频中可能包含一些实际项目的案例,展示不同框架在实际应用中的表现和优势。
331+
4. 未来发展趋势:
332+
探讨 .NET UI 框架的未来发展方向,如 MAUI 的持续演进和 Blazor 在 Web 开发中的应用前景。
333+
334+
## 开源项目
335+
336+
1、[csharpier](https://github.com/belav/csharpier)
337+
338+
![Image](https://github.com/user-attachments/assets/92705d55-6d22-4781-b1ff-6ffd670c915a)
339+
340+
CSharpier 是一个为 C# 和 XML 设计的“有主见”(opinionated)代码格式化工具,旨在通过统一的格式规则提升代码一致性和可读性。它借鉴了 [Prettier](https://prettier.io/) 的理念,使用 Roslyn 解析代码,并根据自身规则重新打印代码,自动处理缩进、换行和空格等格式细节。
341+
342+
✨ 特性
343+
344+
- 统一格式:自动处理缩进、换行和空格,确保代码风格一致。
345+
- 最小配置:仅提供少量配置选项(如缩进宽度、使用空格或制表符),避免团队在格式问题上的争论。
346+
- 快速高效:性能优异,适用于大型项目。
347+
- 广泛集成:支持 Visual Studio、VS Code 等主流 IDE,可设置为保存时自动格式化。
348+
- CI/CD 支持:可作为预提交钩子或在持续集成流程中使用,确保提交代码符合格式规范。
349+
- XML 支持:从 1.0.0 版本起,支持格式化 .csproj、.xml、.config 等 XML 文件。

0 commit comments

Comments
 (0)