为什么我要复制“这个"?在结构中使用 LINQ 时(如果我这样做可以吗)? [英] Why do I have to copy "this" when using LINQ in a struct (and is it OK if I do)?

查看:17
本文介绍了为什么我要复制“这个"?在结构中使用 LINQ 时(如果我这样做可以吗)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The code belows contains a simple LINQ query inside an immutable struct.

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 之外的局部变量表达式或查询表达式并使用本地代替.

Anonymous methods, lambda expressions, and query expressions inside structs cannot access instance members of 'this'. Consider copying 'this' to a local variable outside the anonymous method, lambda expression or query expression and using the local instead.

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

消息建议的修复工作正常:

The fix the message suggests works fine:

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

        return from neighborIndex in NeighborIndexes;
             select thisCopy.GetEdge(neighborIndex);
    }

但这是标准做法吗?是否有理由在结构中没有这样的查询?(从更大的角度来看,制作副本不会让我担心性能方面的问题).

But is this standard practice? Are there reasons for not having queries like this in structs? (In the bigger scheme of things making a copy does not worry me performance-wise as such).

推荐答案

结构体上的实例方法通过引用this一个隐藏的ref参数.
这就是为什么结构体方法能够改变它们被调用的结构体的原因.

Instance methods on structs are called with a reference to this – a hidden ref parameter.
This is why struct methods are able to mutate the structs they're called on.

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

When you use this (or any other local variable / parameter) inside a lambda expression or LINQ query, the compiler turns it into a field on a compiler-generate closure class.

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

The CLR does not support ref fields, so it would be impossible for the captured this to work the same way as a regular this. (this is also the reason that you can't use ref parameters inside lambdas)

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

Iterator methods have the same issue – they are compiled into a hidden enumerator class, and all variables or parameters become fields in the class (this is why iterators cannot take ref parameters).
However, for iterators, C# made the opposite decision. Inside an iterator, you can use this, but it will be copied to a field on the enumerator class.
This means that if you mutate a struct inside an iterator, the mutations will not happen to the caller's copy.

这篇关于为什么我要复制“这个"?在结构中使用 LINQ 时(如果我这样做可以吗)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆