我想调用一个带有两个out
参数和bool
作为返回值的函数。现在我的问题是我看到这两个参数在我调试时被更改了,但是当函数返回时它们仍然会回到length = 0(它们被初始化的方式)。
我已经看到.net-framework 4有一个很好的解决方案,但不幸的是我必须使用.net-framework 3.5。
这是我的代码:
public delegate bool GetAllCheckedItemsDelegate(out int[] cTypes, out int[] cFiles);
public bool GetAllCheckedItems(out int[] cTypes , out int[] cFiles )
{
if (ListView.InvokeRequired)
{
cTypes = new int[0];
cFiles = new int[0];
return (bool)ListView.Invoke(new GetAllCheckedItemsDelegate(GetAllCheckedItems), new object[] { cTypes, cFiles });
}
else
{
cTypes = new int[ListView.CheckedItems.Count];
cFiles = new int[ListView.CheckedItems.Count];
for (int i = 0; i < ListView.CheckedItems.Count; i++)
{
// ......code......
}
return (ListView.CheckedItems.Count > 0);
}
}
答案 0 :(得分:2)
我不太喜欢“out”关键字,那么使用包含信息的类(Row)呢:
using SCG = System.Collections.Generic;
using System.Linq;
public class Row {
public int CheckedType { get; set; }
public int CheckedFile { get; set; }
}
...
public delegate SCG.IEnumerable<Row> GetAllCheckedItemsDelegate();
public bool GetAllCheckedItems() {
if (ListView.InvokeRequired) {
var rows = ListView.Invoke(new GetAllCheckedItemsDelegate(GetAllCheckedItems)
, new object[] {});
return rows.Count() > 0;
} else {
var rows = new SCG.List<Row>();
for (int i = 0; i < ListView.CheckedItems.Count; i++) {
// create and set row
var row = new Row { CheckedType = x, CheckedFile = y };
...
rows.Add(row);
}
return rows.AsReadOnly();
}
}
答案 1 :(得分:1)
return (bool)ListView.Invoke(..., new object[] { cTypes, cFiles });
修改了object []元素。 C#没有提供语法来更新方法的参数,还有一个额外的间接级别,你可以与代码建立桥接。您可以复制参考资料。没什么好担心的,你实际上并没有复制数组内容,只是复制引用:
var args = new object[] { null, null };
var dlg = new GetAllCheckedItemsDelegate(GetAllCheckedItems);
var retval = (bool)ListView.Invoke(dlg, args);
cTypes = (int[])args[0];
cFiles = (int[])args[1];
return retval;
当然没什么好看的。请记住,你肯定在做一些非常不合适的事情,你无法保证你得到了你期望获得的物品。此代码在非常不可预测的时刻运行,与在UI线程上运行的代码完全不相交。如果用户在工作人员运行时忙于检查项目,那么您将获得一个非常随机的选择。列表框的快照状态很快就会变为陈旧状态。
这几乎总是要求您在工作程序运行时禁用列表框,以便保证计算结果与列表匹配。这反过来意味着完全编写这个代码已经不再有用了,你也可以在启动线程之前获取列表。哪个是真正的解决方案。
答案 2 :(得分:0)
我找到了一个适合我的解决方案。如果你认为这不是解决这个问题的好方法,我仍然会接受不同的(和更好的)方法。
public delegate bool BoolDelegate();
public bool GetAllCheckedItems(out int[] cTypes , out int[] cFiles )
{
if (ListView.InvokeRequired)
{
int[] cTypesHelpVar = new int[0];
int[] cFilesHelpVar = new int[0];
bool ret = (bool)ListView.Invoke((BoolDelegate) (() => GetAllCheckedItems(out cTypesHelpVar, out cFilesHelpVar)));
cTypes = cTypesHelpVar;
cFiles = cFilesHelpVar;
return ret;
}
else
{
cTypes = new int[ListView.CheckedItems.Count];
cFiles = new int[ListView.CheckedItems.Count];
for (int i = 0; i < ListView.CheckedItems.Count; i++)
{
//.... code ....
}
return (ListView.CheckedItems.Count > 0);
}
}