解决内联数组声明中的错误和警告
本文介绍了以下编译器错误和警告:
- CS9164:无法将表达式转换为
Span<T>
,因为它不是可赋值变量 - CS9165:无法将表达式转换为
ReadOnlySpan<T>
,因为它可能无法通过引用传递或返回 - CS9166:索引超出内联数组的边界
- CS9167:内联数组长度必须大于 0。
- CS9168:内联数组结构不得具有显式布局。
- CS9169:内联数组结构必须且只能声明一个实例字段,该字段不得为 ref 字段。
- CS9172:只能使用可隐式转换为
int
、System.Index
或System.Range
的单个参数访问内联数组类型的元素。 - CS9173:内联数组访问可能没有已命名的参数说明符
- CS9180:内联数组元素字段不能声明为必需、只读、易失或固定大小缓冲区。
- CS9181:内联数组索引器不会用于元素访问表达式。
- CS9182:内联数组“Slice”方法不会用于元素访问表达式。
- CS9183:内联数组转换运算符不会用于从声明类型的表达式转换。
- CS9184:元素字段是“
ref
”字段,或者作为类型参数具有无效类型的内联数组类型不支持“内联数组”语言功能。 - CS9189:不支持类型内联数组中的语句
foreach
- CS9259:System.Runtime.CompilerServices.InlineArrayAttribute属性不能应用于记录结构。
内联数组声明
将内联数组声明为具有单个字段的 struct
类型,以及指定数组长度的属性。 编译器为无效的内联数组声明生成以下错误:
- CS9167:内联数组长度必须大于 0。
- CS9168:内联数组结构不得具有显式布局。
- CS9169:内联数组结构必须且只能声明一个实例字段,并且该字段不得为 ref 字段。
- CS9180:内联数组元素字段不能声明为必需、只读、易失或固定大小缓冲区。
- CS9184:元素字段是“
ref
”字段,或者作为类型参数具有无效类型的内联数组类型不支持“内联数组”语言功能。 - CS9259:System.Runtime.CompilerServices.InlineArrayAttribute属性不能应用于记录结构。
若要修复这些数组,请确保满足以下条件:
- System.Runtime.CompilerServices.InlineArrayAttribute 的参数是一个正整数。
- 封闭
struct
没有指定任何显式布局。 - 封闭
struct
具有单个实例字段,且该实例字段不是ref
字段。 - 单个实例字段不是固定大小缓冲区。
- 单个实例字段不包括
required
、volatile
或readonly
修饰符。 record
从内联数组声明中删除修饰符。
元素访问
内联数组的元素访问方式与任何数组相同。 编译器会从不正确的元素访问中发出以下错误:
- CS9166:索引超出内联数组的边界
- CS9172:只能使用可隐式转换为
int
、System.Index
或System.Range
的单个参数访问内联数组类型的元素。 - CS9173:内联数组访问可能没有命名参数说明符
- CS9189:不支持类型内联数组中的语句
foreach
此外,编译器会在声明索引器时发出以下警告:
- CS9181:内联数组索引器不会用于元素访问表达式。
内联缓冲区生成的代码可直接访问缓冲区内存,从而绕过任何声明的索引器。 内联数组不能与 foreach
语句一起使用。
索引器的参数必须是:
- 以下三种类型之一:
int
、System.Index
或System.Range
。 - 不能是命名参数。 编译器生成元素访问器。 参数没有名称,因此无法使用命名参数。
- 在数组的边界内。 与所有 .NET 数组一样,内联数组元素访问也会进行边界检查。 索引必须位于内联数组的边界内。
转换为 Span
通常使用 System.Span<T> 或 System.ReadOnlySpan<T> 来处理内联数组。 编译器针对无效转换生成以下错误:
- CS9164:无法将表达式转换为
Span<T>
,因为它不是可赋值变量 - CS9165:无法将表达式转换为
ReadOnlySpan<T>
,因为它可能无法通过引用传递或返回
编译器可生成直接访问内联缓冲区内存的代码。 因此,从未调用过某些成员。 如果编写了一个从未调用的成员,编译器将生成以下警告:
- CS9182:内联数组“Slice”方法不会用于元素访问表达式。
- CS9183:内联数组转换运算符将不用于从声明类型的表达式转换。
内联数组可以隐式转换为 Span<T>
或 ReadOnlySpan<T>
,以将其传递给方法。 编译器对这些转换强制实施限制:
- 内联数组必须可写入,以便转换为
Span<T>
。 如果数组是只读数组,则无法将其转换为可写入的Span<T>
。 可以改用ReadOnlySpan<T>
。 - 内联数组的安全上下文必须至少与
Span<T>
或ReadOnlySpan<T>
的安全上下文一样宽,才能成功进行转换。 必须限制 Span 的上下文,或扩展内联数组的范围。
此外,编译器永远不会在内联缓冲区中生成对 Slice
方法的调用。 不会调用将内联缓冲区转换为 Span
或 ReadOnlySpan
的转换运算符。 编译器会生成代码,以直接从内存缓冲区创建 System.Span<T> 或 System.ReadOnlySpan<T>。