[英]C# lambda ref out
我正在嘗試這樣做,但它不起作用。 一些建議?
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();
};
});
}
為什么我不能將test_i設置為3? 我也試過ref和out,但它不起作用。
我該怎么辦才能修復它?
編輯
我試過這個,但是這個方法dataSet的ouside仍然是空的。
public static void Select(DataGridView dataGridView, ref DataSet dataSet, params object[] parameters)
{
var _dataSet = dataSet;
AsyncCommandExecutor commandExecutor = new AsyncCommandExecutor(System.Threading.SynchronizationContext.Current);
commandExecutor.ExecuteWithContinuation(
() =>
{
// this is the long-running bit
_dataSet = getDataFromDb(parameters);
// This is the continuation that will be run on the UI thread
return () =>
{
dataGridView.DataSource = _dataSet.Tables[0].DefaultView;
};
});
dataSet = _dataSet;
}
lambda表達式中的i
變量指的是方法的參數i
。 作為一種解決方法,您可以使其引用全局變量(臟解決方案)。
順便說一下, 你不能在lambdas中捕獲ref
和out
變量 ,但你可以將它們作為參數。 您需要更改委托的簽名和接收委托的方法的實現,這可能不合適:
(out int i) => { i = 10; }
使用ref
關鍵字傳遞變量時,不能在lambda表達式中使用它。 嘗試在lambda中使用局部變量並在其外部分配ref
變量(如果可能)(稍微簡化的示例):
private static void Main(string[] args)
{
int i = 0;
DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(ref i);
Console.WriteLine(i);
}
public static void DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(ref int i)
{
int temp = i;
Thread t = new Thread(() =>
{
temp = 3; // assign the captured, local variable
});
t.Start();
t.Join();
i = temp; // assign the ref parameter
}
更新
響應更新的答案:您的問題是lambda表達式中的_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
方法將在分配_dataSet
之前_dataSet
執行,因此它將為null
。 為了解決這個問題,您可能希望使用某種信令機制(例如ManualResetEvent
或AutoResetEvent
)來了解分配何時完成。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.