修改C#字典值

时间:2010-03-13 07:54:46

标签: c# data-structures collections

我是C ++专家,但对C#来说根本不是。我创建了一个Dictionary<string, STATS>,其中STATS是一个简单的struct。在我使用初始stringSTATS对构建字典后,我想修改字典的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

3 个答案:

答案 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();
    ...
}