如何通过引用传递 System.Action?
How to pass a System.Action by reference?
我将 System.Action
作为参数传递给一个方法,该方法执行一些冗长的操作并想向调用列表添加更多内容 在 Action
已通过:
class Class1
{
private System.Action onDoneCallback;
void StartAsyncOperation(System.Action onDoneCallback)
{
this.onDoneCallback = onDoneCallback;
// do lengthy stuff
}
void MuchLater()
{
this.onDoneCallBack?.Invoke();
}
}
class Class2
{
public System.Action action;
void DoStuff()
{
action += () => print ("a");
new Class1().StartAsyncOperation(action);
}
{
// ... much later in another place but still before StartAsyncOperation ends
action += () => print ("b");
}
}
但是,只有在将 Action 作为参数传递之前用 +=
添加的内容才会被调用。因此,在此示例中,它只会打印 "a"
而不会打印 "b"
.
这让我觉得 System.Action
在作为参数传递时被 复制了 (就像原始类型,例如 int
会)。所以,后面做+=
的时候,对SomeAsyncOperation
里面的本地副本action
没有影响。
我想通过 System.Action
和 ref
。但是,我需要将它作为成员变量存储在 Class1
中,我不能将成员变量设为 ref
!
所以,基本上,问题是:在回调已经通过并且冗长的操作很长但尚未结束之后,如何向回调的调用列表添加更多内容。
编辑:
结束替换
new Class1().StartAsyncOperation(action);
和
new Class1().StartAsyncOperation(() => action?.Invoke());
一个选项:
class Class2
{
public List<System.Action> callbacks = new List<System.Action>();
void DoStuff()
{
callbacks.Add(() => print("a"));
new Class1().StartAsyncOperation(() => {
forach(var a in callbacks()
{
a();
}
});
}
{
// ... much later in another place but still before StartAsyncOperation ends
callbacks.Add(() => print ("b"));
}
}
您将关闭列表,因此任何更改在回调 运行 时仍然可用。
委托类型是不可变的引用类型,如字符串:
s += "\n";
s
现在是对不同对象的引用。如果将它传递给一个方法,该方法将获得对该对象的引用,而不是 s
下一个可能引用的任何对象。此 lambda returns,并将继续 return,调用 lambda 时 s
所指的任何对象:
() => s;
这同样适用于 a += () => {};
:a
之后引用不同的对象,但是您可以创建一个 lambda 来执行 a
的当前值,无论它是什么。
因此:
new Class1().StartAsyncOperation(() => action());
无论您在那之后做什么 action
,您传入的 lambda 都会引用 action
的当前值。
在家试试:
Action a = () => Console.Write("a");
// This would print "a" when we call b() at the end
//Action b = a;
// This prints "a+" when we call b() at the end.
Action b = () => a();
a += () => Console.Write("+");
b();
我将 System.Action
作为参数传递给一个方法,该方法执行一些冗长的操作并想向调用列表添加更多内容 在 Action
已通过:
class Class1
{
private System.Action onDoneCallback;
void StartAsyncOperation(System.Action onDoneCallback)
{
this.onDoneCallback = onDoneCallback;
// do lengthy stuff
}
void MuchLater()
{
this.onDoneCallBack?.Invoke();
}
}
class Class2
{
public System.Action action;
void DoStuff()
{
action += () => print ("a");
new Class1().StartAsyncOperation(action);
}
{
// ... much later in another place but still before StartAsyncOperation ends
action += () => print ("b");
}
}
但是,只有在将 Action 作为参数传递之前用 +=
添加的内容才会被调用。因此,在此示例中,它只会打印 "a"
而不会打印 "b"
.
这让我觉得 System.Action
在作为参数传递时被 复制了 (就像原始类型,例如 int
会)。所以,后面做+=
的时候,对SomeAsyncOperation
里面的本地副本action
没有影响。
我想通过 System.Action
和 ref
。但是,我需要将它作为成员变量存储在 Class1
中,我不能将成员变量设为 ref
!
所以,基本上,问题是:在回调已经通过并且冗长的操作很长但尚未结束之后,如何向回调的调用列表添加更多内容。
编辑:
结束替换
new Class1().StartAsyncOperation(action);
和
new Class1().StartAsyncOperation(() => action?.Invoke());
一个选项:
class Class2
{
public List<System.Action> callbacks = new List<System.Action>();
void DoStuff()
{
callbacks.Add(() => print("a"));
new Class1().StartAsyncOperation(() => {
forach(var a in callbacks()
{
a();
}
});
}
{
// ... much later in another place but still before StartAsyncOperation ends
callbacks.Add(() => print ("b"));
}
}
您将关闭列表,因此任何更改在回调 运行 时仍然可用。
委托类型是不可变的引用类型,如字符串:
s += "\n";
s
现在是对不同对象的引用。如果将它传递给一个方法,该方法将获得对该对象的引用,而不是 s
下一个可能引用的任何对象。此 lambda returns,并将继续 return,调用 lambda 时 s
所指的任何对象:
() => s;
这同样适用于 a += () => {};
:a
之后引用不同的对象,但是您可以创建一个 lambda 来执行 a
的当前值,无论它是什么。
因此:
new Class1().StartAsyncOperation(() => action());
无论您在那之后做什么 action
,您传入的 lambda 都会引用 action
的当前值。
在家试试:
Action a = () => Console.Write("a");
// This would print "a" when we call b() at the end
//Action b = a;
// This prints "a+" when we call b() at the end.
Action b = () => a();
a += () => Console.Write("+");
b();