为什么我要复制这个?当在结构体中使用LINQ时(如果我这样做是可以的)
本文关键字:如果 这样做 LINQ 复制 我要 结构体 为什么 | 更新日期: 2023-09-27 18:05:51
下面的代码在一个不可变结构体中包含一个简单的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);
}
但这是标准做法吗?在结构体中没有这样的查询是否有原因?(在更大的计划中,制作副本并不会让我担心性能方面的问题)。
结构体上的实例方法是通过引用 this
& &;隐藏的ref
参数。
这就是为什么结构方法能够改变调用它们的结构的原因。
当你在lambda表达式或LINQ查询中使用this
(或任何其他局部变量/参数)时,编译器会将其转换为编译器生成的闭包类的字段。
CLR不支持ref
字段,因此捕获的this
不可能像常规的this
一样工作。(这也是不能在lambdas中使用ref
参数的原因)
迭代器方法也有同样的问题& & &;它们被编译成一个隐藏的枚举器类,所有变量或参数都成为类中的字段(这就是迭代器不能接受ref
形参的原因)。
然而,对于迭代器,c#做出了相反的决定。在迭代器内部,可以使用this
,但它将被复制到枚举器类的一个字段中。
这意味着如果你在迭代器中改变了一个结构体,这种改变不会发生在调用者的副本上。