Skip to content

Commit 1b500c1

Browse files
committed
epside 44
1 parent 5f18237 commit 1b500c1

File tree

2 files changed

+208
-1
lines changed

2 files changed

+208
-1
lines changed

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616

1717
### 2023
1818

19-
**十月份**[第 042 期](docs/episode-043.md) :high_brightness:
19+
**十一月份**[第 044 期](docs/episode-044.md) :high_brightness:
20+
21+
**十月份**[第 043 期](docs/episode-043.md)
2022

2123
**九月份**[第 042 期](docs/episode-042.md) | [第 041 期](docs/episode-041.md)
2224

docs/episode-044.md

+205
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
# .NET 每周分享第 44 期
2+
3+
## 卷首语
4+
5+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/f612de05-a497-471f-9369-2521734d319b)
6+
7+
微软推出了 `.NET 8` Hack [项目](https://devblogs.microsoft.com/dotnet/join-us-for-the-great-dotnet-8-hack/),在 11 月 20 号到 12 月 4 号期间,使用 `.NET 8`开发云原生,AI 或者 MAUI 的项目都可以获取将奖金。
8+
9+
## 行业资讯
10+
11+
1、[F# 编程项目](https://d3s.mff.cuni.cz/teaching/nprg077/)
12+
13+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/289def6b-c148-4356-98ec-3c72e7a15141)
14+
15+
这里包含了四门课程,主要是是通过 `F#` 编写自己的编程系统。
16+
17+
## 文章推荐
18+
19+
1、[Logger Message Generator](https://learn.microsoft.com/en-us/dotnet/core/extensions/logger-message-generator)
20+
21+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/693e3483-0471-48d4-b3d3-c9c03b54dcc1)
22+
23+
Log 的方法的的签名是这样的
24+
25+
```csharp
26+
public static void Log(this ILogger logger, LogLevel logLevel, EventId eventId, Exception? exception, string? message, params object?[] args)
27+
```
28+
29+
显而易见,最后一个参数 `args` 就是格式化参数,类如 `string.format`。如果对内存有了解下的话,这里会出现装箱的操作,比如传参数的类型基本数据类型,就会发生装箱操作。
30+
`.NET 6` 提供了 logger generation 的功能,它可以生成类型匹配的日志方法从而避免的装箱。
31+
32+
```csharp
33+
public static partial class Log
34+
{
35+
[LoggerMessage(EventId = 23, Message = "{name} lives in {city}.")]
36+
public static partial void PlaceOfResidence(this ILogger logger, LogLevel logLevel, string name, string city);
37+
}
38+
```
39+
40+
生成器创建了如下的 `PlaceOfResidence` 方法
41+
42+
```csharp
43+
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "7.0.7.1805")]
44+
public static partial void PlaceOfResidence(this global::Microsoft.Extensions.Logging.ILogger logger, global::Microsoft.Extensions.Logging.LogLevel logLevel, global::System.String name, global::System.String city)
45+
{
46+
if (logger.IsEnabled(logLevel))
47+
{
48+
logger.Log(
49+
logLevel,
50+
new global::Microsoft.Extensions.Logging.EventId(23, nameof(PlaceOfResidence)),
51+
new __PlaceOfResidenceStruct(name, city),
52+
null,
53+
__PlaceOfResidenceStruct.Format);
54+
}
55+
}
56+
```
57+
58+
2、[C# 12 介绍](https://pvs-studio.com/en/blog/posts/csharp/1074/)
59+
60+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/5b5e8e3e-bcc5-432c-985d-5fc93d936281)
61+
62+
C# 12 即将发布,跟这篇文章看看有哪些新的内容
63+
64+
1. 主构造函数
65+
2. 不同初始化集合的方法
66+
3. 匿名方法中的默认参数
67+
4. 类型别名
68+
5. `nameof` 方法
69+
6. 内联数组
70+
7. 代码切入
71+
72+
3、[使用 Contains 而不是使用 IndexOf](https://dotnettips.wordpress.com/2023/10/25/microsoft-net-code-analysis-consider-using-string-contains-instead-of-string-indexof/)
73+
74+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/30c89386-24db-4ec6-8e8d-15558c2aee2a)
75+
76+
.NET Code Analyzer 另外一个建议是选择 `Contains` 而不是 `IndexOf` 来判断一个字符串是否在另一个字符串中。下面是 Benchmark 的结果,可以看出 `Contains` 的性能比 `IndexOf` 要好。
77+
78+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/2ee85ec1-5043-456e-8655-7a9d7572eb33)
79+
80+
4、[自定义嵌入资源文件名](https://www.meziantou.net/customizing-the-embedded-resource-name-in-dotnet.htm)
81+
82+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/91b064ec-705c-4612-b218-02fb62a9ca14)
83+
84+
C# 支持将一个资源文件,比如图片,文本,数据当作资源作为程序集的一部分。默认的文件名为 `<assembly>.<namesapce>.<folder>` 作为文件的路径,但是 `C#` 还支持指定资源名或者做同意的替换
85+
86+
```xml
87+
<Project>
88+
<ItemGroup>
89+
<EmbeddedResource Include="Resources/**/*">
90+
<LogicalName>$([System.String]::new('%(RelativeDir)').Replace('\','/'))%(FileName)%(Extension)</LogicalName>
91+
</EmbeddedResource>
92+
</ItemGroup>
93+
</Project>
94+
```
95+
96+
这样资源的名字就变成和 `Resource` 目录一致的格式。
97+
98+
5、[Pattern Matching 的新用法](https://www.youtube.com/shorts/Av-fv9EOrnw)
99+
100+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/f7b72ec3-d522-4c8e-9579-c3d3884a5124)
101+
102+
模式匹配是 C# 的最近几个版本加入的功能,除了常见的 `switch` 语句查询,还有一个在 `if` 判断的条件中方式
103+
104+
```csharp
105+
var engineer = new Engineer()
106+
{
107+
IsManager = false,
108+
IsSenior = true,
109+
Age = 30
110+
};
111+
112+
113+
if (engineer is
114+
{
115+
IsManager: false,
116+
Age: >18
117+
})
118+
{
119+
Console.WriteLine("Junior Engineer");
120+
}
121+
```
122+
123+
它用来判断一个工程师对象的 `IsManager = false` 而且 `Age` 大于 18,则输出 `Junior Engineer` 的语句。
124+
125+
6、[.NET 8 中的 TimeProvider 类型](https://andrewlock.net/exploring-the-dotnet-8-preview-avoiding-flaky-tests-with-timeprovider-and-itimer/)
126+
127+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/54fdcac0-294b-418c-bede-87ef94b7e288)
128+
129+
千呼万唤始出来,`.NET 8` 终于提供了一个公开的时间接口,这样方便我们进行测试,它是一个叫做 `TimeProvider` 的抽象类,
130+
131+
```csharp
132+
public abstract class TimeProvider
133+
{
134+
public static TimeProvider System { get; }
135+
136+
protected TimeProvider();
137+
138+
public virtual TimeZoneInfo LocalTimeZone { get; }
139+
public virtual long TimestampFrequency { get; }
140+
141+
public DateTimeOffset GetLocalNow();
142+
public virtual DateTimeOffset GetUtcNow();
143+
public virtual long GetTimestamp();
144+
public TimeSpan GetElapsedTime(long startingTimestamp);
145+
public TimeSpan GetElapsedTime(long startingTimestamp, long endingTimestamp);
146+
147+
public virtual ITimer CreateTimer(TimerCallback callback, object? state,TimeSpan dueTime, TimeSpan period);
148+
}
149+
```
150+
151+
其中 `GetLocalNow()``GetUtcNow` 用来返回相应的时间。
152+
153+
7、[C# 性能比较的正确方式](https://sergeyteplyakov.github.io/Blog/benchmarking/2023/11/02/Performance_Comparison_For_Classes_vs_Structs.html)
154+
155+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/7bb1c554-6c28-4568-bf8f-7bde031d1b69)
156+
157+
我们都知道使用 benchmark 来测算不同方式,数据类型的性能。但是在针对获取的数据时候,需要记住以下几点
158+
159+
1. 不要信任你不能解释的东西,尤其是微观上的benchmark
160+
2. 理解你测量的东西,不要着急下结论
161+
3. 看到表面之下的东西,在性能分析之下,考虑更多抽象之下的内容
162+
4. 要非常小心 Linq 的细节
163+
164+
8、[Visual Studio 中配置私有字段命名规则](https://ardalis.com/configure-visual-studio-to-name-private-fields-with-underscore/#sq_het4wkszkg)
165+
166+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/05f72f5c-882d-4aba-a4a0-1739c6a68b00)
167+
168+
在 C# 中有一些明明规则,比如类和方法选择驼峰命名法,类中私有字段要求有下划线作为前缀,等等。所以在 `Visual Studio` 中配置相应的规则,可以帮助我们找到不符合规则的命名方式。
169+
170+
171+
9、[Func, Predict 和 Expression 的区别](https://www.youtube.com/watch?v=PoniDOq5zQw&ab_channel=MilanJovanovi%C4%87)
172+
173+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/a9b5c5b8-a380-46d5-9d88-33c6a3a5e335)
174+
175+
C# 中存在三种判断类型的委托,分别为
176+
177+
- `Func<T, bool>`
178+
- `Predicate<T>`
179+
- `Expression<Func<T, bool>>`
180+
181+
三者的区别可以用这一段代码表示
182+
183+
```csharp
184+
Func<User, bool> userFunc = user => user.Age > 29;
185+
186+
Predicate<User> userPredicate = user => user.Age > 29;
187+
188+
Expression<Func<User, bool>> userEf = user => user.Age > 29;
189+
190+
User user = new User { Age = 29 };
191+
192+
if (userFunc(user)
193+
|| userPredicate(user)
194+
|| userEf.Compile()(user))
195+
{
196+
197+
}
198+
```
199+
200+
10、[Span](https://blog.ndepend.com/improve-c-code-performance-with-spant/)
201+
202+
![image](https://github.com/DotNETWeekly-io/DotNetWeekly/assets/11272110/b1943a70-ae72-4463-9a23-78d2bd83e0f0)
203+
204+
205+
我们都知道 `Span` 类型能够提高 C# 代码运行的性能,那么它是究竟怎么做到的呢?这边文章给出了更加详细的解释。

0 commit comments

Comments
 (0)