C# 道具中的私有初始化?

private init in C# props?

C# 中 init only setterprivate 访问修饰符是什么意思?对于我域 类 中的大多数属性,我通常将 setter 设为私有。 init,有关系吗?

以下似乎没有任何问题,编译器没有报错。

public class Point
{
    public int X { get; private init; }
    public int Y { get; private init; }
}

所以上面和下面有什么不同。下面没有私信。

public class Point
{
    public int X { get; init; }
    public int Y { get; init; }
}

它会影响 setter 的调用位置,就像正常的 setter 一样。

考虑这段代码:

public class Point
{
    public int X { get; private init; }
    public int Y { get; private init; }
}

class Program
{
    static void Main()
    {
        var point = new Point { X = 10, Y = 20 };
    }
}

因两个编译时错误而失败:

The property or indexer 'Point.X' cannot be used in this context because the set accessor is inaccessible

(以及 Y 的等价物)。

相同的初始值设定项在 Point class 中是有效的,因为可以在那里访问集合访问器。例如,您可能想要使用 public 工厂方法,它是通过对象初始值设定项实现的:

public class Point
{
    public int X { get; private init; }
    public int Y { get; private init; }

    public static Point FromXY(int x, int y) =>
        new Point { X = x, Y = y };
}

(有多种原因导致这可能不理想,或者您可能更愿意将参数添加到私有构造函数,但这是 一个示例 私有 init-only setter 可以访问。)

同样,如果没有 set 访问器的 private 部分,上面的代码也是有效的,因为它们可以从任何地方调用(作为对象初始化程序的一部分)。

在 c# 9.0 中添加了 init 关键字,以便在对象上添加不可变属性。

我们曾经遇到的问题是,如果您有这个对象,您仍然可以通过 public 方法修改名称 属性(尽管它有一个私有的 setter)。例如:

public class Person
{
    public Person(string name)
    {
        this.Name = name;
    }

    public void SetName(string name)
    {
        this.Name = name;
    }

    public string Name { get; private set; }
}

而且我们也不能使用对象初始化器

var person = new Person
{
    Name = "Jane Doe" // Compile Error 
};

现在,如果我们将代码更改为使用 init

public class Person
{
    public Person(string name)
    {
        this.Name = name;
    }

    public string Name { get; init; }
}

我们现在可以使用对象初始化器

var person = new Person
{
    Name = "Jane Doe" // No error
};

但是,如果我们像您的示例一样使用您的private init

public class Person
{
    public Person(string name)
    {
        this.Name = name;
    }

    public string Name { get; private init; }
}

我们将无法使用对象初始化器

var person = new Person
{
    Name = "Jane Doe" // Compile error
};