解决不安全代码构造中的错误和警告

本文介绍以下编译器错误:

  • CS0193* 或 -> 运算符必须应用于数据指针
  • CS0196指针必须仅索引一个值
  • CS0208无法获取地址、获取其大小或声明指向托管类型的指针('type')
  • CS0209固定语句中声明的本地类型必须是指针类型
  • CS0210必须在固定声明或 using 语句声明中提供初始值设定项
  • CS0211无法获取给定表达式的地址
  • CS0212只能在固定语句初始值设定项内获取未固定表达式的地址
  • CS0213不能使用固定语句获取已固定表达式的地址
  • CS0214指针和固定大小缓冲区只能在不安全的上下文中使用
  • CS0227仅当使用 /unsafe 进行编译时,才会显示不安全代码
  • CS0233“identifier”没有预定义的大小,因此 sizeof 只能在不安全的上下文中使用
  • CS0242该操作在 void 指针上未定义
  • CS0244is”和“”as在指针类型上都无效
  • CS0254固定语句赋值右侧不能是强制转换表达式
  • CS0459无法获取只读局部变量的地址
  • CS0821无法修复隐式类型局部变量
  • CS1641固定大小缓冲区字段必须在字段名称后面具有数组大小说明符
  • CS1642固定大小缓冲区字段只能是结构的成员。
  • CS1656无法分配给“variable”,因为它是“只读变量类型”
  • CS1663固定大小的缓冲区类型必须是以下类型之一:bool、、byteshortintlong、、char、、sbyteushortuint、或 ulongfloatdouble
  • CS1665固定大小缓冲区的长度必须大于零
  • CS1666不能使用未固定表达式中包含的固定大小缓冲区。请尝试使用固定语句。
  • CS1708固定大小缓冲区只能通过局部变量或字段访问
  • CS1716请勿使用“System.Runtime.CompilerServices.FixedBuffer”属性。请改用“固定”字段修饰符。
  • CS1919对象创建中不能使用不安全类型“类型名称”。
  • CS4004在不安全的上下文中无法await
  • CS8812无法将组转换为 &Method 非函数指针类型。
  • CS9123&“运算符不应用于异步方法中的参数或局部变量。

指针操作和解引用

  • CS0193*->运算符必须应用于数据指针
  • CS0196指针必须仅索引一个值
  • CS0242所涉及的操作在 void 指针上是未定义的

若要正确使用指针作,请遵循取消引用、索引和算术运算的规则。 有关详细信息,请参阅指针类型和函数指针

  • 仅将 *-> 运算符应用于数据指针(CS0193)。 不要将这些运算符用于非点器类型或函数指针。 与 C/C++ 不同,无法在 C# 中取消引用函数指针。
  • 仅包含一个值的索引指针(CS0196)。 指针不支持多维索引。
  • 避免在 void 指针(CS0242)上执行未定义的操作。 例如,不要递增 void 指针,因为编译器不知道要指向的数据的大小。

指针类型和托管类型

  • CS0208不能取得托管类型('type')的地址、大小,或声明其指针
  • CS0233“identifier”没有预定义的大小,因此 sizeof 只能在不安全的上下文中使用

若要正确处理指针和 sizeof 运算符,请使用非托管类型和正确的上下文。 有关详细信息,请参阅非托管类型和sizeof运算符

  • 仅对非托管类型(CS0208)使用指针。 不要获取托管类型的地址、获取其大小或声明指向托管类型的指针。 托管类型包括引用类型和包含引用类型字段或属性的结构。
  • 在大小不是编译时常量(CS0233)的类型的unsafe上下文中使用sizeof运算符。

固定缓冲区

  • CS0209固定语句中声明的本地类型必须是指针类型
  • CS0210必须在固定声明或 using 语句声明中提供初始值设定项
  • CS0211无法获取给定表达式的地址
  • CS0212只能在固定语句的初始化器中获取未固定的表达式的地址
  • CS0213不能使用固定语句获取已固定表达式的地址
  • CS0254固定语句赋值右侧可能不是强制转换表达式
  • CS0459无法获取只读局部变量的地址
  • CS0821无法修复隐式类型局部变量
  • CS1656无法分配给“variable”,因为它是“只读变量类型”

错误地使用 fixed 语句 时,会发生这些错误。 该 fixed 语句可防止垃圾回收器重新定位可移动变量并声明指向该变量的指针。 有关详细信息,请参阅 不安全代码和指针

要正确使用 fixed 语句:

  • 将变量声明为指针类型(CS0209)。
  • fixed 语句声明中提供初始化器(CS0210)。
  • 仅获取有效表达式的地址:字段、局部变量和指针间接(CS0211)。 不要采用计算表达式的地址,如两个变量的总和。
  • 仅在语句初始值设定项(fixed)中使用未修复表达式的地址运算符。
  • 不要对已修复的表达式使用 fixed 语句(CS0213)。 方法中的 unsafe 局部变量和参数已经固定在堆栈上。
  • 不要在fixed语句赋值的右侧使用强制转换表达式(CS0254)。
  • 不要获取只读局部变量(CS0459)的地址。 foreach 循环、using 语句和fixed 语句中的变量是只读的。
  • 使用显式类型而非在 fixed 语句中使用 var (CS0821)。
  • 不要在只读上下文(如 foreach 循环、 using 语句或 fixed 语句(CS1656)中分配给变量。

不安全的上下文限制

  • CS0214指针和固定大小缓冲区只能在不安全的上下文中使用
  • CS0227仅当使用 /unsafe 进行编译时,才会显示不安全代码
  • CS0244“is”和“as”在指针类型上都无效
  • CS1919创建对象时无法使用不安全类型“类型名称”
  • CS4004无法在不安全的上下文中等待
  • CS9123不应在异步方法中对参数或局部变量使用‘&’运算符

当你使用不安全的代码构造而不使用适当的不安全上下文或尝试不安全代码中不允许的作时,会发生这些错误。 有关详细信息,请参阅 不安全代码和指针 以及 unsafe 关键字

正确地使用不安全代码:

  • 标记使用指针或固定大小缓冲区的方法、类型或代码块,使用关键字 unsafeCS0214)。
  • 使用关键字(CS0227)时,在项目设置中启用 unsafe 编译器选项。
  • 不要在指针类型中使用isas运算符(CS0244)。 这些类型测试运算符对指针无效。
  • 请勿使用 new 运算符创建指针类型实例(CS1919)。 若要在非托管内存中创建对象,请使用互操作调用返回指针的原生方法。
  • 将不安全代码与异步代码(CS4004)分开。 为不安全的操作创建单独的方法,并在异步方法中调用它们。
  • 不要对异步方法(&)中的参数或局部变量使用地址运算符()。 异步作完成时,变量可能不存在。

固定大小的缓冲区

  • CS1641固定大小缓冲区字段必须在字段名称后面具有数组大小说明符
  • CS1642固定大小缓冲区字段只能是结构的成员
  • CS1663固定大小的缓冲区类型必须是下列值之一:bool、byte、short、int、long、char、sbyte、ushort、uint、ulong、float 或 double
  • CS1665固定大小缓冲区的长度必须大于零
  • CS1666不能使用未固定表达式中包含的固定大小缓冲区。尝试使用固定语句
  • CS1708固定大小缓冲区只能通过局部变量或字段访问
  • CS1716请勿使用“System.Runtime.CompilerServices.FixedBuffer”属性。改用“固定”字段修饰符

使用固定大小的缓冲区时,会发生这些错误。 固定大小的缓冲区是直接嵌入在结构中的数组,主要用于互作方案。 有关详细信息,请参阅 固定大小的缓冲区

若要正确声明和使用固定大小的缓冲区,请执行以下作:

  • 使用正整数常量(CS1641CS1665)在字段名称后面指定数组大小。
  • 仅在结构中声明固定大小的缓冲区,而不是在类中(CS1642)。 如果需要类中的字段,请使用常规数组。
  • 使用受支持的元素类型之一:bool、、byteshortintlongcharsbyteushortuintulong、或 floatdoubleCS1663)。
  • 在访问缓冲区之前使用fixed语句来固定包含结构(CS1666)。
  • 仅通过局部变量或字段(而不是中间表达式(CS1708)访问固定大小的缓冲区。
  • fixed使用字段修饰符而不是System.Runtime.CompilerServices.FixedBuffer属性(CS1716)。

函数指针

  • CS8812无法将组转换为 &Method 非函数指针类型

若要获取函数指针,请使用具有显式函数指针类型强制转换的地址运算符。 请勿使用 地址运算符 & 将方法组 void* 分配给其他非函数指针类型。 有关详细信息,请参阅 函数指针