通过


使用 lambda 表达式和匿名函数时出现错误和警告

多个 错误 与声明和使用 lambda 表达式匿名方法有关:

  • CS0407“method”返回类型错误。
  • CS0428无法将方法组“Identifier”转换为非委托类型“type”。是否打算调用该方法?
  • CS0748lambda 参数用法不一致;参数类型必须是全部显式或全部隐式的。
  • CS0815无法将“表达式”分配给隐式类型的变量。
  • CS0828无法将“expression”分配给匿名类型属性。
  • CS0837“is”或“as”运算符的第一个作数可能不是 lambda 表达式、匿名方法或方法组。
  • CS1065默认值在此上下文中无效。
  • CS1621yield 语句不能在匿名方法或 lambda 表达式中使用。
  • CS1628不能在匿名方法、lambda 表达式或查询表达式中使用 inrefout 参数。
  • CS1632控制不能离开匿名方法或 lambda 表达式的正文。
  • CS1643并非所有代码路径都返回类型为“type”的匿名方法中的值。
  • CS1660无法将 lambda 表达式转换为类型“type”,因为它不是委托类型。
  • CS1661无法将匿名方法块转换为类型“type”,因为参数类型与委托参数类型不匹配。
  • CS1662无法将匿名方法块转换为预期委托类型,因为块中的某些返回类型无法隐式转换为委托返回类型。
  • CS1673结构内的匿名方法、lambda 表达式和查询表达式无法访问“this”的实例成员。
  • CS1676必须使用“keyword”关键字声明参数“number”。
  • CS1677不应使用“keyword”关键字声明参数“number”。
  • CS1678参数“number”声明为类型“type1”,但应为“type2”。
  • CS1686局部变量或其成员无法获取其地址,并且不能在匿名方法或 lambda 表达式中使用。
  • CS1688在没有参数列表的情况下,无法将匿名方法块转换为委托类型“delegate”,因为它具有一个或多个 out 参数。
  • CS1706表达式不能包含匿名方法或 lambda 表达式。
  • CS1731无法将表达式转换为委托,因为块中的某些返回类型无法隐式转换为委托返回类型。
  • CS1732预期参数。
  • CS1764无法在匿名方法、lambda 表达式或查询表达式中使用固定本地。
  • CS8030转换为 void 返回委托的匿名函数无法返回值。
  • CS8175无法在匿名方法、lambda 表达式或查询表达式中使用 ref local。
  • CS8820静态匿名函数不能包含对“variable”的引用。
  • CS8821静态匿名函数不能包含对“this”或“base”的引用。
  • CS8916lambda 表达式的属性需要带括号的参数列表。
  • CS8917无法推断委托类型。
  • CS8934无法将匿名方法转换为类型“type”,因为返回类型与委托返回类型不匹配。
  • CS8975上下文关键字 var 不能用作显式 lambda 返回类型。
  • CS9098隐式类型 lambda 参数“...”不能有默认值。

此外,多个 警告 与声明和使用 lambda 表达式相关:

  • CS0467方法“method”和非方法“non-method”之间存在歧义。将使用方法组解决。
  • CS1911通过匿名方法、lambda 表达式、查询表达式或迭代器中的“base”关键字访问成员将导致无法验证的代码。
  • CS8971在应用于 lambda 参数时,InterpolatedStringHandlerArgument 不起作用,将在调用站点被忽略。
  • CS8974将方法组“method”转换为非委托类型“type”。是否打算调用该方法?
  • CS9099默认参数值与目标委托类型不匹配。
  • CS9100参数在 lambda 中具有参数修饰符,但在目标委托类型中没有参数修饰符。

编译器还会生成以下 信息性 消息:

  • CS9236编译需要至少绑定 lambda 表达式的计数时间。考虑使用显式参数类型声明 lambda 表达式,或者如果包含的方法调用是泛型的,请考虑使用显式类型参数。

lambda 表达式中的语法限制

  • CS0837isas 运算符的第一个操作数不能是 lambda 表达式、匿名方法或方法组。
  • CS1621语句 yield 不能在匿名方法或 lambda 表达式中使用。
  • CS1628不能在匿名方法、lambda 表达式或查询表达式中使用inrefout参数。
  • CS1632控制不能离开匿名方法或 lambda 表达式的正文。
  • CS1673结构内的匿名方法、lambda 表达式和查询表达式无法访问实例 this成员。
  • CS1686局部变量或其成员无法获取其地址,并且不能在匿名方法或 lambda 表达式中使用。
  • CS1706表达式不能包含匿名方法或 lambda 表达式。
  • CS1764无法在匿名方法、lambda 表达式或查询表达式中使用固定本地。
  • CS1911:警告: 通过匿名方法、lambda 表达式、查询表达式或迭代器中的“base”关键字访问成员将导致无法验证的代码。
  • CS8175无法在匿名方法、lambda 表达式或查询表达式中使用 ref local。
  • CS8820静态匿名函数不能包含对“variable”的引用。
  • CS8821静态匿名函数不能包含对“this”或“base”的引用。
  • CS8971:警告: 在应用于 lambda 参数时,InterpolatedStringHandlerArgument 不起作用,将在调用站点上忽略。
  • CS9236:信息提示:编译时需要多次绑定 lambda 表达式。考虑显式声明 lambda 表达式的参数类型,或者如果所调用的方法是泛型的,请考虑使用显式类型参数。

编译器禁止 lambda 表达式匿名方法内的某些 C# 构造。 存在这些限制,因为编译器将 lambda 和匿名方法转换为 委托 调用或 表达式树,并且某些构造不能在这些形式中表示。 有关详细信息,请参阅 C# 规范的 匿名函数表达式 部分。

可以使用以下指南更正这些错误:

  • 将任何yield returnyield break语句移出 lambda 正文并放入封闭迭代器方法,或将 lambda 转换为支持语句(yield)的本地函数
  • 避免在 lambda 正文中引用封闭方法的inrefout参数。 当 lambda 捕获这些参数作为 闭包的一部分时,无法保留类似于 ref 的参数的引用语义。 将该值复制到局部变量,并改用该局部变量,或将 lambda 转换为本地函数(CS1628)。
  • 删除将控制权转移出 lambda 正文的任何 breakgotocontinue 语句。 控制流语句必须针对同一 lambda 表达式主体中的标签或循环(CS1632)。
  • struct 类型中,避免在 lambda 表达式、匿名方法或查询表达式中通过 this 引用实例成员。 由于编译器按值this捕获struct,因此 lambda 内部的突变不会影响原始实例。 在 lambda 之前将所需的成员值提取到局部变量中,或转换为可以直接访问 this 的本地函数(CS1673)。
  • 不要获取 lambda 也捕获的局部变量的地址。 编译器将捕获的变量移动到堆分配的闭包对象,使其地址不稳定。 将寻址逻辑与 lambda 分离,或使用本地函数(CS1686)。
  • 将 lambda 表达式或匿名方法移出限制其功能的包含表达式。 某些表达式(如属性构造函数)不支持 lambda 表达式或匿名方法作为参数(CS1706)。
  • 不要在 lambda 正文中使用 fixed 局部变量。 语句的fixed固定保证仅适用于封闭范围,不适用于编译器生成的闭包(CS1764)。
  • 请勿在 ref lambda 正文中使用本地。 像 ref 参数一样,ref 局部变量无法在编译器为 lambda 生成的闭包中被捕获。 将值分配给非ref 局部变量,或将 lambda 转换为本地函数(CS8175)。
  • 请勿将 lambda 表达式、匿名方法或方法组作为 isas 运算符的第一个操作数。 这些构造没有可在运行时测试的类型。 先将表达式分配给变量,然后测试变量(CS0837)。
  • static从 lambda 中删除修饰符,或删除对捕获的变量的引用。 static lambda 显式禁止捕获局部变量、参数或this以避免不必要的闭包分配。 如果需要引用外部变量,请删除 static 修饰符。 如果要将堆分配保持最小,请将值作为参数传递给 lambda (CS8820CS8821)。
  • 删除 lambda 参数中的 InterpolatedStringHandlerArgumentAttribute 标签,或者将逻辑移动到遵循该属性的方法中。 编译器会忽略 lambda 参数上的此属性,因为 lambda 调用不使用与常规方法调用(CS8971)相同的插值字符串处理器降级方式。
  • 避免通过 base 关键字在 lambda 或匿名方法内部调用虚拟成员。 编译器通过帮助程序方法生成非虚拟调用,该方法生成无法验证的代码。 请考虑将 base 调用提取到一个单独的方法中,然后从 lambda 调用该方法(CS1911)。
  • 减少那些接受 lambda 表达式的重载方法调用的复杂性,或者添加显式类型信息。 当编译器多次绑定 lambda 表达式以解析重载时,它将发出此信息诊断。 使用 显式参数类型声明 lambda 或在泛型方法调用中提供显式类型参数,可以减少编译器必须执行的绑定数(CS9236)。

Lambda 表达式参数和返回

  • CS0748lambda 参数用法不一致;参数类型必须是全部显式或全部隐式的。
  • CS1065默认值在此上下文中无效。
  • CS1643并非所有代码路径都返回类型为“type”的匿名方法中的值。
  • CS1661无法将匿名方法块转换为类型“type”,因为参数类型与委托参数类型不匹配。
  • CS1662无法将匿名方法块转换为预期委托类型,因为块中的某些返回类型无法隐式转换为委托返回类型。
  • CS1676必须使用“keyword”关键字声明参数“number”。
  • CS1677不应使用“keyword”关键字声明参数“number”。
  • CS1678参数“number”声明为类型“type1”,但应为“type2”。
  • CS1688在没有参数列表的情况下,无法将匿名方法块转换为委托类型“delegate”,因为它具有一个或多个 out 参数。
  • CS1731无法将表达式转换为委托,因为块中的某些返回类型无法隐式转换为委托返回类型。
  • CS1732预期参数。
  • CS8030转换为 void 返回委托的匿名函数无法返回值。
  • CS8916lambda 表达式的属性需要带括号的参数列表。
  • CS8934无法将匿名方法转换为类型“type”,因为返回类型与委托返回类型不匹配。
  • CS8975上下文关键字“var”不能用作显式 lambda 返回类型。
  • CS9098隐式类型 lambda 参数“...”不能有默认值。

这些错误表示 lambda 表达式参数 或返回类型声明出现问题。 有关 lambda 参数和返回类型的完整规则,请参阅 C# 规范的 lambda 表达式匿名方法和匿名函数表达式部分。

注释

CS1731CS1732 不再由 C# 编译器的当前版本 (Roslyn) 生成。 如果你使用的是较旧的编译器版本,则可能会显示它们。

可以使用以下指南更正这些错误:

  • 确保 lambda 表达式中的所有参数都使用相同的键入样式。 当 lambda 具有多个参数时,每个参数都必须 显式类型 化或隐式类型化—不能在同一参数列表中混合这两种样式(CS0748)。
  • 将显式类型添加到具有 默认值的任何 lambda 参数。 编译器需要对具有默认值的参数显式类型,因为它必须生成对默认值进行编码的自定义委托类型。 隐式类型参数不能为编译器提供足够的信息,因此无法构造该委托类型(CS1065CS9098)。
  • 从使用 delegate 运算符声明的匿名方法中删除默认参数值。 默认参数值仅在 lambda 表达式中受支持,而不支持匿名方法。 如果需要默认值(CS1065),请将匿名方法转换为 lambda 表达式。
  • 将 lambda 或匿名方法的参数类型、ref/out/in修饰符和参数计数与目标委托类型匹配。 编译器在将匿名函数转换为委托时会进行参数签名的精确匹配:每个参数必须具有正确的类型,并且任何refoutin修饰符都必须正如委托所期望的那样存在(CS1661CS1676CS1677CS1678)。
  • 当目标委托类型具有 out 参数时,将参数列表添加到匿名方法。 不使用参数列表(使用 delegate { } 语法)声明的匿名方法可以匹配大多数委托类型,但编译器无法隐式合成所需的 out 参数。 显式声明参数以匹配委托签名(CS1688)。
  • 确保当目标委托类型具有非 void 返回类型时,lambda 或匿名方法中的所有代码路径都返回一个值。 每个代码块中的分支必须返回一个可隐式转换为委托返回类型的值(CS1643CS1662CS1731CS8934)。
  • 从分配给return返回委托类型的 lambda 或匿名方法中删除具有值的任何void语句,例如Action。 由于委托的返回类型为 void,因此正文无法返回值(CS8030)。
  • 属性 应用于任何 lambda 参数时,请将参数列表括在括号中。 编译器需要带括号的形式来区分属性语法与其他表达式。 例如,写入 ([MyAttribute] int x) => x 而不是 [MyAttribute] x => xCS8916)。
  • 使用特定类型名称,而不是 var 用作 lambda 表达式的显式返回类型。 该关键字 var 保留为 隐式类型的局部变量 ,不能用作 lambda 返回类型注释。 指定实际返回类型,或省略返回类型,让编译器推断它(CS8975)。
  • 修复参数列表,使编译器能够将其识别为有效的参数声明。 此错误表示格式不正确的参数列表,编译器需要参数标识符,但找到了其他内容(CS1732)。

Lambda 表达式委托类型

  • CS0407“method”返回类型错误。
  • CS0428无法将方法组“Identifier”转换为非委托类型“type”。是否打算调用该方法?
  • CS0467:警告: 方法“method”与非方法“非方法”之间的歧义性。使用方法组。
  • CS0815无法将“表达式”分配给隐式类型的变量。
  • CS0828无法将“expression”分配给匿名类型属性。
  • CS1660无法将 lambda 表达式转换为类型“type”,因为它不是委托类型。
  • CS8917无法推断委托类型。
  • CS8974:警告: 将方法组“method”转换为非委托类型“type”。是否打算调用该方法?
  • CS9099:警告: 默认参数值与目标委托类型不匹配。
  • CS9100:警告: 参数在 lambda 中具有参数修饰符,但在目标委托类型中没有参数修饰符。

这些错误表示编译器推断或期望 lambda 表达式匿名方法方法组委托类型出现问题。 有关委托转换的完整规则,请参阅 C# 规范的 lambda 表达式匿名方法和匿名函数表达式部分。

注释

C# 编译器(Roslyn)的当前版本不生成 CS0467。 如果使用较旧的编译器版本,可能会看到此错误。

可以使用以下指南更正这些错误:

  • 确保工作分配或转换的目标类型为 委托类型System.Linq.Expressions.Expression。 不能将 lambda 表达式或匿名方法分配给非委托类型,例如 object 或接口。 将变量的类型更改为兼容的委托类型,比如Func<>Action<>,或者使用var让编译器推断委托类型(CS1660)。
  • 为编译器提供足够的上下文,以确定 lambda 表达式的单个委托类型。 分配到 var时,编译器需要明确的返回类型和参数列表。 分配给匿名类型属性时,编译器根本无法推断委托类型。 将 lambda 分配给具有显式委托类型的变量,然后在匿名类型初始值设定项(CS0815CS0828CS8917)中使用该变量。
  • 将方法组的返回类型与委托的声明返回类型匹配。 方法组转换要求方法的返回类型可标识转换或隐式转换为委托的返回类型。 更改方法的返回类型,或更改委托类型以匹配(CS0407)。
  • 目标类型不是委托时,应该调用方法,而不是分配方法组。 如果目标类型为 stringint另一个非委托类型,则你可能打算调用该方法并分配其结果。 添加括号和参数以调用方法(CS0428,CS8974)。
  • 解决方法与共享同名的非方法成员之间的歧义。 重命名其中一个冲突成员,或使用完全限定的引用删除歧义(CS0467)。
  • 当目标委托类型为标准Func<>Action<>类型时,从 lambda 中删除默认参数值修饰符。 默认值和 params 修饰符会导致编译器生成的自定义委托类型不匹配 Func<>Action<>。 要么使用var来让编译器合成正确的委托类型,要么删除默认值或params修饰符,以便 lambda 能匹配声明的委托类型(CS9099, CS9100)。