我有一个关于自 C# 8 以来可用的可为空引用类型系统的问题。
假设我们有一个带有可变引用类型属性的 C# 域模型类,如下所示:
public class Person
{
public string Name { get; set; }
public Person(string name)
{
Name = name;
}
}
Run Code Online (Sandbox Code Playgroud)
到目前为止没有问题。但考虑现实世界的场景,我经常想检查属性的有效性,因为它是一个公共可变属性,我必须确保模型在属性更改时保持不变。
public class Person
{
private string _name;
public string Name
{
get => _name;
set => _name = value ?? throw new ArgumentNullException("Name is required.");
}
public Person(string name)
{
Name = name;
}
}
Run Code Online (Sandbox Code Playgroud)
然后编译器生成CS8618警告,基本上是说
“不可为空的字段 _name 未初始化。考虑将该字段声明为可为空类型。”
因此,每次遇到警告时,我都必须用以下 pragma 指令将构造函数括起来。
#pragma warning disable CS8618
public Person(string name)
{ …
Run Code Online (Sandbox Code Playgroud) 我在尝试将项目从 .NET core 3.1 升级到最新的 .NET 5 时遇到了不兼容的问题。
我的原始代码有一个验证逻辑,通过检查从 Path.GetInvalidFileNameChars() API 返回的每个字符来检查无效的文件名字符。
var invalidFilenameChars = Path.GetInvalidFileNameChars();
bool validFileName = !invalidFilenameChars.Any(ch => fileName.Contains(ch, StringComparison.InvariantCulture));
Run Code Online (Sandbox Code Playgroud)
假设您为 fileName 提供了一个常规值,例如应该有效的“test.txt”。然而,令人惊讶的是,如果您使用“net5”目标框架运行,上面的代码给出的文件名无效。
在调试了一段时间后,我发现返回的无效字符集包含 '\0'、空 ASCII 字符和 "text.txt".Contains("\0, StringComparison.InvariantCulture) 为真。
class Program
{
static void Main(string[] args)
{
var containsNullChar = "test".Contains("\0", StringComparison.InvariantCulture);
Console.WriteLine($"Contains null char {containsNullChar}");
}
}
Run Code Online (Sandbox Code Playgroud)
如果您在 .NET core 3.1 中运行,它永远不会说常规字符串包含空字符。此外,如果我省略第二个参数 (StringComparison.InvariantCulture) 或者如果我使用 StringComparison.Ordinal,则永远不会返回奇怪的结果。
为什么在 .NET5 中改变了这种行为?
编辑: 正如 Karl-Johan Sjögren 之前所评论的,.NET5 中确实存在关于字符串比较的行为变化:
另请参阅相关票证:
string.IndexOf 在 .Net 5 中得到不同的结果
虽然这个问题应该与上面有关,但与 …
我去年刚开始用 C# 编程,我还在学习这门语言。我有一个关于readonly struct
类型和相等比较方法的问题。
在 C# 中创建结构时,我知道实现IEquatable通常被认为是最佳实践,因为默认的基于反射的比较非常慢。我还了解到,在 C# 7.2 及更高版本中,我们可以定义readonly
结构,对于这些类型,我们还可以使用in
参数来避免不必要的复制。
由于结构通常被定义为不可变的只读类型,我认为为只读结构定义 Equals 方法并不罕见。
然而,鉴于上述事实,我想知道是否有一种有效的方法来为它们实现相等比较方法。我的观点是,这些相等方法和运算符实际上都不需要修改参数,因此我想以in
某种方式利用参数来节省不必要的复制。
以下是我在这样做的尝试:
public readonly struct Point : IEquatable<Point>
{
public int X { get; }
public int Y { get; }
public Point(int x, int y)
{
X = x;
Y = y;
}
// Explicitly implementing IEquatable<Point> and delegating to an Equals method taking in param.
bool IEquatable<Point>.Equals(Point other) => Equals(other);
public bool Equals(in Point …
Run Code Online (Sandbox Code Playgroud)