为什么在结构中使用LINQ时必须复制“this”(如果我这样做,那么它是否可以)?

下面的代码在不可变结构中包含一个简单的LINQ查询。

struct Point { static readonly List NeighborIndexes; //and other readonly fields! public IEnumerable GetEdges() { return from neighborIndex in NeighborIndexes; select GetEdge(neighborIndex); } } 

它不编译。

结构体内的匿名方法,lambda表达式和查询表达式无法访问“this”的实例成员。 考虑将“this”复制到匿名方法,lambda表达式或查询表达式之外的局部变量,并使用local。

有谁知道为什么不允许这样做?

修复消息建议工作正常:

  public IEnumerable GetEdges() { var thisCopy = this; return from neighborIndex in NeighborIndexes; select thisCopy.GetEdge(neighborIndex); } 

但这是标准做法吗? 是否有理由在结构中没有这样的查询? (在制作副本的更大方案中,并不担心我的表现如此)。

结构的实例方法通过引用来调用 – 隐藏的ref参数 。
这就是struct方法能够改变它们被调用的结构的原因。

在lambda表达式或LINQ查询中使用this (或任何其他局部变量/参数)时,编译器会将其转换为编译器生成闭包类的字段。

CLR不支持ref字段,因此捕获的字段不可能像常规字一样工作。 (这也是你不能在lambdas中使用ref参数的原因)

迭代器方法具有相同的问题 – 它们被编译成隐藏的枚举器类,并且所有变量或参数都成为类中的字段(这就是迭代器不能接受ref参数的原因)。
但是,对于迭代器,C#做出了相反的决定。 在迭代器中,您可以使用this ,但它将被复制到枚举器类的字段中。
这意味着如果你在迭代器中改变一个结构,突变将不会发生在调用者的副本中。