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

Her*_*ken 16 c# linq struct

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

struct Point
{
   static readonly List</*enum*/> NeighborIndexes;
   //and other readonly fields!

    public IEnumerable<FlatRhombPoint> GetEdges()
    {
        return from neighborIndex in NeighborIndexes;
             select GetEdge(neighborIndex);
    }
}
Run Code Online (Sandbox Code Playgroud)

它不编译.

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

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

修复消息建议工作正常:

    public IEnumerable<FlatRhombPoint> GetEdges()
    {
        var thisCopy = this;

        return from neighborIndex in NeighborIndexes;
             select thisCopy.GetEdge(neighborIndex);
    }
Run Code Online (Sandbox Code Playgroud)

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

SLa*_*aks 20

在结构实例方法调用一个参考this- 一个隐藏的ref参数.
这就是结构方法能够改变它们被调用的结构的原因.

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

CLR不支持ref字段,因此捕获this的工作方式不可能与常规工作方式相同this.(这也是你不能ref在lambdas中使用参数的原因)

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