小编Ryo*_*sai的帖子

使用参数验证初始化可变不可空属性时避免 CS8618 警告

我有一个关于自 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)

c# c#-8.0 nullable-reference-types

9
推荐指数
5
解决办法
4057
查看次数

C# "anyString".Contains('\0', StringComparison.InvariantCulture) 在 .NET5 中返回 true 但在旧版本中返回 false

我在尝试将项目从 .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 中确实存在关于字符串比较的行为变化:

在 .NET 5+ 上比较字符串时的行为变化

另请参阅相关票证:

string.IndexOf 在 .Net 5 中得到不同的结果

虽然这个问题应该与上面有关,但与 …

c# .net-5 c#-9.0

9
推荐指数
1
解决办法
561
查看次数

为只读结构实现相等的最佳实践是什么?

我去年刚开始用 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)

c# struct c#-7.2

5
推荐指数
1
解决办法
520
查看次数

标签 统计

c# ×3

.net-5 ×1

c#-7.2 ×1

c#-8.0 ×1

c#-9.0 ×1

nullable-reference-types ×1

struct ×1