我是C ++专家,但对C#来说根本不是。我创建了一个Dictionary<string, STATS>
,其中STATS
是一个简单的struct
。在我使用初始string
和STATS
对构建字典后,我想修改字典的STATS
值。在C ++中,它非常清楚:
Dictionary<string, STATS*> benchmarks;
Initialize it...
STATS* stats = benchmarks[item.Key];
// Touch stats directly
但是,我在C#中试过这样的事情:
Dictionary<string, STATS> benchmarks = new Dictionary<string, STATS>();
// Initialize benchmarks with a bunch of STATS
foreach (var item in _data)
benchmarks.Add(item.app_name, item);
foreach (KeyValuePair<string, STATS> item in benchmarks)
{
// I want to modify STATS value inside of benchmarks dictionary.
STATS stat_item = benchmarks[item.Key];
ParseOutputFile("foo", ref stat_item);
// But, not modified in benchmarks... stat_item is just a copy.
}
这是一个非常新手的问题,但不容易找到答案。
编辑:我也尝试过以下内容:
STATS stat_item = benchmarks[item.Key];
ParseOutputFile(file_name, ref stat_item);
benchmarks[item.Key] = stat_item;
但是,我得到了异常,因为这样的动作使Dictionary无效:
Unhandled Exception: System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
at System.Collections.Generic.Dictionary`2.Enumerator.MoveNext()
at helper.Program.Main(String[] args) in D:\dev\\helper\Program.cs:line 75
答案 0 :(得分:10)
如果您的STATS
确实是struct
,则表示它是值类型,因此您可以执行以下操作:
STATS stat_item = benchmarks[item.Key];
ParseOutputFile("foo", ref stat_item);
您的stat_item
是位于benchmarks[item.Key]
的值的副本。因此,当您将ref
参数传递给ParseOutputFile
时,只会修改副本。
在您发布的C ++代码中,请注意您将使用指针执行您要完成的操作。
对于.NET,解决方案很简单:将STATS
更改为引用类型(class
而不是struct
)。然后,您的本地stat_item
变量将引用benchmarks[item.Key]
值引用的同一对象。
答案 1 :(得分:2)
您应该将STATS更改为类。然后你不需要ref关键字,对象就会改变。
C#中的常见建议是使用类,除非您绝对确定需要结构。
答案 2 :(得分:0)
试试这个:
STATS stat_item = benchmarks[item.Key];
ParseOutputFile("foo", ref stat_item);
benchmarks[item.Key] = stat_item;
请注意,即使STATS是一个类,然后更新引用(如ref关键字所暗示的)只会更新本地引用stat_item,而不是字典中的值。
例如,如果STATS是一个类,则以下代码将修改字典中的值(但在这种情况下,不需要ref关键字,应删除它):
ParseOutputFile(string foo, ref STATS statItem)
{
statItem.SomeProperty = ...
}
但是以下只会影响局部变量,并且不会更新字典值,即使STATS是一个类:
ParseOutputFile(string foo, ref STATS statItem)
{
statItem = new STATS();
...
}