下面的代码在不可变结构中包含一个简单的LINQ查询。
struct Point
{
static readonly List</*enum*/> NeighborIndexes;
//and other readonly fields!
public IEnumerable<FlatRhombPoint> GetEdges()
{
return from neighborIndex in NeighborIndexes;
select GetEdge(neighborIndex);
}
}
它无法编译。
内部的匿名方法,lambda表达式和查询表达式 结构不能访问'this'的实例成员。考虑复制 'this'到匿名方法lambda之外的局部变量 表达式或查询表达式并使用本地代替。
有人知道为什么不允许这样做吗?
邮件建议的修复工作正常:
public IEnumerable<FlatRhombPoint> GetEdges()
{
var thisCopy = this;
return from neighborIndex in NeighborIndexes;
select thisCopy.GetEdge(neighborIndex);
}
但这是标准做法吗?是否有理由在结构中没有这样的查询? (在制作副本的更大方案中,并不担心我的表现如此)。
答案 0 :(得分:20)
结构的实例方法使用引用调用this
- a hidden ref
parameter。
这就是结构方法能够改变它们被调用的结构的原因。
在lambda表达式或LINQ查询中使用this
(或任何其他局部变量/参数)时,编译器会将其转换为compiler-generate closure class上的字段。
CLR不支持ref
字段,因此捕获的this
无法以与常规this
相同的方式工作。 (这也是你不能在lambdas中使用ref
参数的原因)
迭代器方法有同样的问题 - 它们被编译成一个隐藏的枚举器类,所有变量或参数都成为类中的字段(这就是迭代器不能接受ref
参数的原因)。
但是,对于迭代器,C#做出了相反的决定。在迭代器中,您can use this
,但它将被复制到枚举器类的字段中
这意味着如果你在迭代器中改变一个struct,那么突变就不会发生在调用者的副本中。