You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用in参数触发CS1628错误:无法在lambda表达式中引用该参数

为什么在Lambda表达式中使用in修饰的结构体参数会触发CS1628错误?

你碰到的这个编译错误,本质上是C#编译器的一个设计限制——尽管toMatch是in参数而非ref/out参数,但它的传递语义和ref readonly完全一致,属于按引用传递的参数范畴,而Lambda表达式(包括匿名方法、LINQ查询表达式)出于生命周期安全的考虑,不允许捕获这类引用传递的参数。

先还原你的示例代码:

public readonly struct Point { 
    public Point(int x, int y) { X = x; Y = y; } 
    public int X { get; } 
    public int Y { get; } 
} 

public IEnumerable<Point> FindMatching(this IEnumerable<Point> points, in Point toMatch) { 
    return points.Where(p => p.X == toMatch.X && p.Y == toMatch.Y); 
}

编译时抛出的CS1628错误确实容易让人困惑,因为错误信息直接提到了ref/out参数,但背后的逻辑是:in参数的核心是避免结构体复制,通过只读引用传递,而Lambda的延迟执行特性(比如LINQ的Where是延迟执行的)可能导致原参数的生命周期结束后,Lambda还在尝试引用它,这会带来悬空引用的风险。因此编译器直接禁止了这类捕获行为。

解决方法

这里有两种常用的解决方案:

  1. 复制in参数到局部变量
    把in参数的值复制到一个局部变量中,让Lambda捕获这个局部值类型变量——局部变量的生命周期由编译器管理,不会有悬空引用的问题:
public IEnumerable<Point> FindMatching(this IEnumerable<Point> points, in Point toMatch) { 
    Point matchCopy = toMatch; // 将in参数的值复制到局部变量
    return points.Where(p => p.X == matchCopy.X && p.Y == matchCopy.Y); 
}
  1. 移除in修饰符,改为按值传递
    如果你的Point结构体很小,复制的性能成本可以忽略,直接去掉in修饰符,让参数按值传递,这样Lambda可以直接捕获参数:
public IEnumerable<Point> FindMatching(this IEnumerable<Point> points, Point toMatch) { 
    return points.Where(p => p.X == toMatch.X && p.Y == toMatch.Y); 
}

内容的提问来源于stack exchange,提问作者Jimmy Bogard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:08:50