C#lambda参考输出
我试着这么做,但没用。有什么建议吗C#lambda参考输出,c#,.net,.net-3.5,lambda,C#,.net,.net 3.5,Lambda,我试着这么做,但没用。有什么建议吗 int test_i = 0; DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(test_i); test_i <- still is 0 and not 3!!! public void DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(int i) { DisableUi(); m_commandExecutor
int test_i = 0;
DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(test_i);
test_i <- still is 0 and not 3!!!
public void DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(int i)
{
DisableUi();
m_commandExecutor.ExecuteWithContinuation(
() =>
{
// this is the long-running bit
ConnectToServer();
i = 3; <--------------------------
// This is the continuation that will be run
// on the UI thread
return () =>
{
EnableUi();
};
});
}
lambda表达式中的
i
变量引用方法的参数i
。作为一种解决方法,您可以使其引用全局变量(脏解决方案)
顺便说一下,但是你可以把它们作为参数。您需要更改代理的签名和接收代理的方法的实现,这可能不合适:
(out int i) => { i = 10; }
使用
ref
关键字传递变量时,不能在lambda表达式中使用它。如果可能,尝试在lambda内部使用局部变量,并在其外部指定ref
变量(稍微简化的示例):
更新作为对更新答案的回应:您的问题是lambda表达式内部的
\u dataSet
与lambda表达式外部的dataSet不是同一个变量。您可以执行以下操作:
class DataSetContainer
{
public DataSet DataSet { get; set; }
}
现在,我们有了一个引用类型,它具有一个可以在lambda表达式中安全修改的属性:
public static void Select(DataGridView dataGridView,
DataSetContainer dataSetContainer,
params object[] parameters)
{
AsyncCommandExecutor commandExecutor = new AsyncCommandExecutor(System.Threading.SynchronizationContext.Current);
commandExecutor.ExecuteWithContinuation(
() =>
{
// this is the long-running bit
dataSetContainer.DataSet = getDataFromDb(parameters);
// This is the continuation that will be run on the UI thread
return () =>
{
dataGridView.DataSource = _dataSet.Tables[0].DefaultView;
};
});
}
}
在上面的代码中,lambda表达式将更新传递给Select
方法的DataSetContainer
实例的DataSet
属性。由于您不是在修改传递的参数本身,而是只修改该实例的一个成员,因此不需要使用ref
关键字,而且我们还绕过了闭包问题
更新2现在,当我打开我的大脑时,我意识到
Select
方法发出一个异步调用。很可能代码看起来最后一行是Select
方法将在\u dataSet
分配之前很久执行,因此它将null
。为了解决这个问题,您可能需要研究使用某种信号机制(例如ManualResetEvent
或AutoResetEvent
)来了解分配何时完成。是否可以像我的示例中那样使用它,但使用数据集而不是int i?@Jooj:如果传递引用类型,您应该能够在lambda表达式中修改其成员属性/字段。我更新了答案。希望有帮助:o)
class DataSetContainer
{
public DataSet DataSet { get; set; }
}
public static void Select(DataGridView dataGridView,
DataSetContainer dataSetContainer,
params object[] parameters)
{
AsyncCommandExecutor commandExecutor = new AsyncCommandExecutor(System.Threading.SynchronizationContext.Current);
commandExecutor.ExecuteWithContinuation(
() =>
{
// this is the long-running bit
dataSetContainer.DataSet = getDataFromDb(parameters);
// This is the continuation that will be run on the UI thread
return () =>
{
dataGridView.DataSource = _dataSet.Tables[0].DefaultView;
};
});
}