C# 9 'init' 属性是否可以安全地用于配置绑定 (IOptions)?

Are C# 9 'init' properties safe to use for configuration binding (IOptions)?

我注意到 C# 版本 9 中的新 init 属性在强类型选项 类(选项模式)中使用时似乎会绑定。

换句话说,这个有效:

    class SomeSettings
    {
        public string FirstSetting { get; init; }
        public bool SecondSetting { get; init; }
    }

    ...

    configuration.GetSection(nameof(SomeSettings)).Get<SomeSettings>();

但是我们应该注意任何潜在的 'gotchas' 或限制吗?(当与直接绑定一起使用,或作为 IOptions<> 注入时Configure().)

诚然,我的动机是我正在考虑在配置时直接将这些实例绑定并注册为单例,而不使用讨厌的 IOptions<> 包装器。到目前为止我还没有这样做的唯一原因是属性的可变性,但 init 似乎解决了这个问题。

init 在 IL 中降低为 set 属性。这是有意的,以便设置属性的反射将继续与 init 一起工作,所以这是安全的。

有关更多信息,请参阅关于此起始 here, and specifically this 评论的讨论:

I think this is a matter of cost to benefit.

这确实是一种成本效益权衡,经过讨论,我们决定支持 init 在现有场景中工作,而不是让这些场景中的每一个都发生变化以支持 init 属性的成本。

What is the most popular nuget package you can find which this will adversely affect because they'll set something they shouldn't?

这里要考虑的另一个方面是您希望执行多远?这里要记住的一点是运行时提供只读实例字段的零强制执行。这意味着反射,即使是 public 反射,今天也可以完全只读,并且不会因此受到惩罚。

在讨论这些类型的包时,我们在 LDM 中考虑的一个方面是“将 init 访问器保持在比只读字段更高的标准的价值是什么?我们得出的答案是没有太多价值这样做。

反射已经可以使对象不变性失效,而且这种情况极不可能改变。因此,通过让 init 可以被反射访问,我们并没有改变这里的语义,我们只是适应现有的系统。从这个意义上说,从我们的角度来看,这里的权衡是非常合理的。