通常,可以使用 null-forgiving 运算符 (!) 来抑制可空性警告。我刚刚遇到 CS8670 – 对象或集合初始值设定项隐式取消引用可能为 null 的成员 并尝试使用 null-forgiving 运算符抑制它,但是那没有用,或者更准确地说我不知道将它放在哪里。这是一个例子:
class Program {
public void M() {
var x = new A
{
// Warning is here, when initializing "Items"
Items = { "Hello", "World" }
};
}
}
class A {
public List<string>? Items { get; init;} = new List<string>();
}
A
的代码在外部程序集中,所以我无法修改它。是否可以使用 null-forgiving 运算符抑制 CS8670?
如果这是一次性的场景,那么
#nullable disable
/#nullable restore
对,正如@Guru 提到的那样应该是好的。
另一种选择是放弃使用集合初始化器,而是使用
Items
访问 !
然后是 !
var x = new A();
x.Items!.Add("Hello");
x.Items!.Add("World");
// or
var items = x.Items!;
items.Add("Hello");
items.Add("World");
如果您发现这是代码中的常见模式并且发现这些解决方案不方便,您 可以 围绕此类引入一个包装器,但我认为这 太多了,无法解决可空性警告。因此,仅针对您的特定情况做出明智的判断:
using System;
using System.Collections.Generic;
// depending on how you are using "x", then var might work as well.
A x = new AWrapper
{
Items = { "Hello", "World" }
};
class A
{
public List<string>? Items { get; init; } = new List<string>();
}
public readonly struct AWrapper
{
private readonly A _a = new();
public AWrapper()
{
}
public List<string> Items => _a.Items!;
public static implicit operator A(AWrapper wrapper) => wrapper._a;
}
!
是一元后缀运算符,似乎 ATM 它不能用于这种特殊情况,它基本上被翻译成一系列 Add
调用(@sharplab):
A a = new A();
a.Items.Add("Hello");
a.Items.Add("World");
您可以尝试使用
#nullable disable
:
var x = new A
{
#nullable disable
Items = { "Hello", "World" }
#nullable restore
};
或者只是创建一个新的列表实例:
var x = new A
{
Items = new(){ "Hello", "World" }
};
就个人而言,“一般情况下”我会选择第二个选项(除非是对性能非常敏感的代码),因为不能保证库作者在某个时候不会删除默认初始化。