Tutorial :Modifying C# dictionary value



Question:

I'm a C++ expert, but not at all for C#. I created a Dictionary<string, STATS>, where STATS is a simple struct. Once I built the dictionary with initial string and STATS pairs, I want to modify the dictionary's STATS value. In C++, it's very clear:

Dictionary<string, STATS*> benchmarks;  Initialize it...    STATS* stats = benchmarks[item.Key];  // Touch stats directly  

However, I tried like this in 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.  }  

This is a really novice problem, but wasn't easy to find an answer.

EDIT: I also tried like the following:

  STATS stat_item = benchmarks[item.Key];    ParseOutputFile(file_name, ref stat_item);    benchmarks[item.Key] = stat_item;  

However, I got the exception since such action invalidates 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  


Solution:1

If your STATS is indeed a struct, that means it's a value type, so where you do this:

STATS stat_item = benchmarks[item.Key];  ParseOutputFile("foo", ref stat_item);  

Your stat_item is a copy of the value located at benchmarks[item.Key]. Thus when you pass it as a ref parameter to ParseOutputFile, only the copy is modified.

In the C++ code you posted, notice you would do what you're trying to accomplish here by using a pointer.

For .NET, the solution is simple: change STATS to a reference type (a class rather than struct). Then your local stat_item variable will be a reference to the same object referenced by the value of benchmarks[item.Key].


Solution:2

You should just change STATS to a class. Then you wouldn't need the ref keyword and the object would change.

The usual advice in C# is to use classes unless you are absolutely certain you need a struct.


Solution:3

Try this:

STATS stat_item = benchmarks[item.Key];   ParseOutputFile("foo", ref stat_item);   benchmarks[item.Key] = stat_item;  

Note that even if STATS is a class, then updating the reference (as is implied by the ref keyword) will only update the local reference stat_item, not the value in the dictionary.

For example, the following code will modify the value in the dictionary if STATS is a class (but in this case the ref keyword is not needed and should be removed):

ParseOutputFile(string foo, ref STATS statItem)  {      statItem.SomeProperty = ...  }  

But the following will only affect the local variable and won't update the dictionary value, even if STATS is a class:

ParseOutputFile(string foo, ref STATS statItem)  {      statItem = new STATS();      ...  }  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »