解决委托指针和函数指针的错误和警告

本文介绍了以下编译器错误和警告:

  • CS0059不一致的可访问性:参数类型 'type' 的可访问性低于委托 'delegate' 的可访问性。
  • CS0123“method”的重载均与委托“delegate”不匹配。
  • CS0148委托类型“delegate”没有有效的构造函数。
  • CS0410“method”的重载均没有正确的参数类型和返回类型。
  • CS0644“class”无法从特殊类“class”派生。
  • CS1599方法、委托或函数指针的返回类型不能为“type”。
  • CS1958对象和集合初始值设定项表达式不能应用于委托创建表达式。
  • CS8755“修饰符”不能用作函数指针参数的修饰符。
  • CS8756函数指针“type”不采用“count”参数。
  • CS8757“method”的重载均与函数指针“type”不匹配。
  • CS8758“method”和函数指针“type”之间的 Ref 不匹配。
  • CS8759无法为“method”创建函数指针,因为它不是静态方法。
  • CS8786“convention”的调用约定与“convention”不兼容。
  • CS8787无法将方法组转换为函数指针。(你缺少“&”吗?
  • CS8788不可将具有接收器的扩展方法用作“&”运算符的目标。
  • CS8789固定语句中声明的本地类型不能是函数指针类型。
  • CS8806语言不支持“约定”的调用约定。
  • CS8807“说明符”不是函数指针的有效调用约定说明符。
  • CS8808“modifier”不是有效的函数指针返回类型修饰符。有效的修饰符为“ref”和“ref readonly”。
  • CS8809返回类型只能有一个“modifier”修饰符。
  • CS8811无法将 &method 组“method”转换为委托类型“type”。
  • CS8909函数指针的比较可能会产生意外的结果,因为指向同一函数的指针可能不同。
  • CS8911不支持在此上下文中使用函数指针类型。

委托签名不匹配

  • CS0059不一致的可访问性:参数类型 '类型' 的可访问性比委托 '委托' 的可访问性更低。
  • CS0123“method”的重载均与委托“delegate”不匹配。
  • CS0148委托“delegate”没有有效的构造函数。
  • CS0410“method”的重载均没有正确的参数类型和返回类型。

创建或分配委托时,编译器会验证目标方法的签名是否与委托类型的声明匹配。 签名包括参数类型、返回类型和辅助功能。 有关完整规则,请参阅 C# 规范中的 委托辅助功能约束

  • 将委托声明中的所有参数类型更改为至少与委托本身一样可访问的类型(CS0059)。 public委托无法在其参数列表中引用访问权限较低的类型,因为程序集外部的调用方无法提供该参数。 有关详细信息,请参阅 访问修饰符
  • 调整方法签名或委托签名,使参数类型和返回类型完全匹配(CS0123)。 将方法分配给委托时,编译器需要完全匹配的签名。
  • 验证委托是否已由符合性编译器(CS0148)编译。 当您导入由编译器生成且包含格式错误的委托构造函数的托管程序集时,会发生此错误。 使用符合标准的编译器重新编译程序集以解决错误。

注释

CS0410 不再由当前 C# 编译器生成。 现在,相同的条件将生成 CS0123。 使用早期编译器编译的旧程序集可能仍引用此错误代码。

CS0148 是仅限构建诊断:

注释

仅在显式构建重新构建操作期间报告此警告。 在 IDE 中键入时,它不会作为 IntelliSense 诊断的一部分出现。 这意味着,如果通过使用字段或移除字段来修复警告,那么在重新生成或再次生成项目之前,警告可能仍会保留在错误列表中。

委托类型限制

  • CS0644“class”无法从特殊类“class”派生。
  • CS1599方法、委托或函数指针的返回类型不能为“type”。
  • CS1958对象和集合初始值设定项表达式不能应用于委托创建表达式。

C# 语言限制如何使用某些特殊类型,包括 System.Delegate. 有关委托声明的完整规则,请参阅 C# 规范中的 委托委托

  • 删除显式基类并改用 delegate 声明(CS0644)。 类不能显式继承自System.DelegateSystem.EnumSystem.ValueTypeSystem.Array。 编译器将这些类型用作隐式基类。 例如,每个 delegate 声明都隐式派生自 System.Delegate.
  • 将返回类型更改为允许作为返回值的类型(CS1599)。 .NET类库中的某些类型(如 TypedReferenceRuntimeArgumentHandleArgIterator)不能用作方法、委托或函数指针的返回类型,因为它们可能会启用不安全的堆栈操作。
  • 删除委托创建表达式(CS1958)后的大括号。 委托没有可以通过对象或集合初始值设定项语法设置的成员。 如果在 new DelegateType(method) 表达式之后有 { } ,请删除大括号。

函数指针签名不匹配

  • CS8755“修饰符”不能用作函数指针参数的修饰符。
  • CS8756函数指针“type”不采用“count”参数。
  • CS8757“method”的重载均与函数指针“type”不匹配。
  • CS8758“method”和函数指针“type”之间的引用不匹配。
  • CS8759无法为“method”创建函数指针,因为它不是静态方法。
  • CS8787无法将方法组转换为函数指针。(你缺少“&”吗?
  • CS8788不可将具有接收器的扩展方法用作“&”运算符的目标。
  • CS8811无法将 &method 组“method”转换为委托类型“type”。

使用 address-of(&) 运算符将方法分配给函数指针时,编译器会检查该方法的签名是否与函数指针类型匹配。 有关函数指针声明和用法的完整规则,请参阅 函数指针不安全代码

  • 从函数指针参数中删除不支持的修饰符(CS8755)。 函数指针参数仅支持refoutin修饰符。 其他参数修饰符(例如 params)在函数指针类型声明中无效。
  • 更改调用站点的参数数以匹配函数指针的参数计数(CS8756)。 函数指针类型定义固定数量的参数,必须准确传递许多参数。
  • 调整方法的签名,使其参数类型、返回类型和参数计数与函数指针类型(CS8757)匹配。 与委托不同,函数指针不支持兼容方法签名之间的隐式转换。 匹配必须精确。
  • 在方法的参数与函数指针类型的参数之间对齐refoutin修饰符(CS8758)。 每个参数的 ref 类型必须完全匹配。 参数ref不能满足函数指针类型中的inout位置。
  • 将目标方法更改为 staticCS8759)。 函数指针只能指向静态方法,因为它们表示没有关联的对象实例的原始函数地址。
  • 在分配给函数指针(&)时,在方法组之前添加运算符。 与委托不同,函数指针需要显式地址运算符: delegate*<void> ptr = &MyMethod;.
  • 使用静态方法而不是具有接收器的扩展方法(CS8788)。 运算符 & 需要直接方法引用。 对实例调用的扩展方法具有无法在函数指针中捕获的隐式接收器。
  • 删除&运算符并使用委托语法,或者将目标类型从委托更改为函数指针(CS8811)。 运算符 & 生成函数指针,而不是委托。 若要将方法组分配给委托类型,请省略 & 并使用标准委托创建语法。

函数指针调用约定和返回类型

  • CS8786“convention”的调用约定与“convention”不兼容。
  • CS8806语言不支持“约定”的调用约定。
  • CS8807“说明符”不是函数指针的有效调用约定说明符。
  • CS8808“modifier”不是有效的函数指针返回类型修饰符。有效的修饰符为“ref”和“ref readonly”。
  • CS8809返回类型只能有一个“modifier”修饰符。

函数指针声明包括调用约定和可选的返回类型修饰符。 编译器验证这些选项。 有关完整规则,请参阅 函数指针

  • 更改方法的调用约定或函数指针类型的调用约定,使其匹配(CS8786)。 将方法分配给函数指针时,调用约定必须兼容。 例如,使用Cdecl的方法不能分配给用Stdcall声明的函数指针。
  • 在函数指针声明(CS8806)中使用受支持的调用约定。 语言支持 managedunmanaged。 对于特定的非托管调用约定,使用unmanaged关键字,并在方括号中指定约定,例如unmanaged[Cdecl]unmanaged[Stdcall]unmanaged[Thiscall]unmanaged[Fastcall]
  • 将无效说明符替换为受支持的调用约定(CS8807)。 在方括号(例如 unmanaged[Cdecl])中将 managedunmanagedunmanaged 与调用约定类型结合使用。
  • refref readonly 可用作返回类型修饰符(CS8808)。 其他修饰符(如 outin)对函数指针返回类型无效。
  • 删除重复的返回类型修饰符,以便只显示一个 refref readonlyCS8809)。 编译器最多允许函数指针声明上的一个返回类型修饰符。

函数指针使用限制

  • CS8789固定语句中声明的本地类型不能是函数指针类型。
  • CS8909函数指针的比较可能会产生意外的结果,因为指向同一函数的指针可能不同。
  • CS8911不支持在此上下文中使用函数指针类型。

编译器限制在特定上下文中使用函数指针类型的方式。 有关完整规则,请参阅 函数指针

  • 将语句中的 fixed 局部变量类型更改为数据指针类型,而不是函数指针类型(CS8789)。 该 fixed 语句将托管对象固定到内存中以进行数据访问。 函数指针表示代码地址,而不是数据,并且无法固定。
  • 避免比较函数指针是否相等(CS8909)。 此警告指示将函数指针与 ==!= 可能会产生意外结果进行比较。 由于实现详细信息(如 thunking 或 JIT 编译),运行时可能会为同一函数返回不同的指针。 若要在确认您是有意进行比较时抑制警告,请使用 #pragma warning disable CS8909
  • 将函数指针用法移动到受支持的上下文(CS8911)。 不能在某些位置(如属性参数或 typeof 表达式)中使用函数指针类型。 重构代码以避免在不支持的上下文中使用函数指针类型。