Изменение значения словаря C#

Я - эксперт C++, но нисколько для C#. Я создал a 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;

Однако я получил исключение, так как такое действие делает недействительным Словарь:

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
5
задан minjang 13 March 2010 в 08:01
поделиться

3 ответа

Если ваш 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].

10
ответ дан 13 December 2019 в 05:33
поделиться

Просто замените STATS на класс. Тогда вам не понадобится ключевое слово ref, и объект изменится.

Обычный совет в C # - использовать классы, если вы не уверены, что вам нужна структура.

2
ответ дан 13 December 2019 в 05:33
поделиться

Попробуйте так:

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();
    ...
}
0
ответ дан 13 December 2019 в 05:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: