我正在创建一个匿名方法并将其传递给稍后要调用的操作。我想将一些数字数据(regex = r'\b(%s)\b' % "|".join(words)
re.search(regex, positive_words)
)传递给我的匿名方法。为了按值传递数据,我是否需要创建副本?或者,数据是否会按值传递?
如果我不得不创建副本,我认为实现会是这样的:
int
是否需要(以上代码)以便按值获取private void CreateAction()
{
int bus = 4;
CustomObject[] data = new object[16];
int length = 1500;
this.doWorkLater = new Action(() =>
{
var busCopy = bus;
var dataCopy = data;
var lengthCopy = length;
this.WorkMethod(busCopy, dataCopy, lengthCopy);
});
}
和length
?
在这种情况下,bus
(我创建的某个类)会通过引用还是按值传递?
答案 0 :(得分:1)
闭包可以通过引用 * 显着捕获值 - 请注意,如果CreateAction
的整个点创建一个单独的操作,那么您所拥有的代码并不能解决问题。
private void CreateAction()
{
int bus = 4;
this.doWorkLater = new Action(() =>
{
var busCopy = bus;
this.WorkMethod(busCopy);
});
// if you change local `bus` before call to `doWorkLater` it will not work:
bus = 42;
doWorkLater(); // busCopy is 42.
}
* 它实际上收集了编译器创建的类中的所有变量,并使用对它的引用来访问方法和闭包中的变量。因此,即使值类型看起来也像通过引用传递一样。
答案 1 :(得分:1)
您传递的内容不是按值复制。
如果您在执行操作之前不打算修改值,则无需担心如何传递值。但他们并没有超越价值。即使你从另一个方法返回动作和Invoke
它。值保存在编译器生成的类中。无需担心
如果您希望在执行操作之前更改数据,那么您做错了。您正在使用的方法(将值类型复制到局部变量)应该在操作之外而不是在其内部完成。对于引用类型(Array),即使将其复制到局部变量,也会复制它所引用的引用,以便反映复制局部变量的任何更改。
private void CreateAction()
{
int bus = 4;
CustomObject[] data = new object[16];
int length = 1500;
var busCopy = bus; // a copy of bus
var dataCopy = data; // reference copy
var lengthCopy = length; // a copy of length
this.doWorkLater = new Action(() =>
{
this.WorkMethod(busCopy, dataCopy, lengthCopy);
});
bus = 10; // No effect on the action
length = 1700; // No effect on the action
this.doWorkLater();
}
这看起来毫无意义,但有时您可能需要将局部变量复制到另一个局部变量,然后再将其传递给匿名方法。检查此Valid Example,修复报告的意外行为!
答案 2 :(得分:0)
这可以帮助您弄清楚发生了什么。
如果你从这个略微简化的课程开始:
public class Example
{
private void CreateAction()
{
int bus = 4;
object[] data = new object[16];
int length = 1500;
Action doWorkLater = () =>
{
var busCopy = bus;
var dataCopy = data;
var lengthCopy = length;
this.WorkMethod(busCopy, dataCopy, lengthCopy);
};
doWorkLater.Invoke();
}
public void WorkMethod(int bus, object[] data, int length)
{
}
}
...然后编译器基本上生成这个:
public class Example
{
private void CreateAction()
{
Example.GeneratedClass closure = new Example.GeneratedClass();
closure.parent = this;
closure.bus = 4;
closure.data = new object[16];
closure.length = 1500;
// ISSUE: method pointer
IntPtr method = __methodptr(closure.CreateAction);
new Action((object)closure, method)();
}
public void WorkMethod(int bus, object[] data, int length)
{
}
[CompilerGenerated]
private sealed class GeneratedClass
{
public int bus;
public object[] data;
public int length;
public Example parent;
internal void CreateAction()
{
this.parent.WorkMethod(this.bus, this.data, this.length);
}
}
}
闭包中捕获的局部变量不再是方法的局部变量,而是生成类中的公共字段。
现在你所知道的关于C#和类的一切都适用。