2010-03-13 418 views
5

我是C++專家,但對C#沒有任何幫助。我創建了Dictionary<string, STATS>,其中STATS是一個簡單的struct。一旦我用stringSTATS對創建字典,我想修改字典的STATS值。在C++中,這是非常清楚的:修改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 
+4

呃,你應該在C++世界中留下那些大寫字母。它在C#中看起來很糟糕。微軟的命名準則建議使用Pascal案例。 – 2010-03-13 07:59:55

+0

結構是值類型,因此這是相同的,然後聲明一個本地雙重,因此新的stat_item是字典記錄的副本。如果STATS是一個類,那麼它是一個參考,然後它會起作用。 – weismat 2010-03-13 08:01:38

+0

這是一個非常簡單的玩具解析程序。 :D實際上,我仍然喜歡用Windows C++風格編寫代碼,但現在我不得不遵循Google的指南......對不起! – minjang 2010-03-13 08:08:16

回答

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]的同一對象。

+0

謝謝,它運作良好。我不知道這樣的語義。 – minjang 2010-03-13 08:05:52

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

你應該改變STATS爲一個類。那麼你不需要ref關鍵字,對象會改變。

在C#中的通常建議是使用類,除非你完全確定你需要需要結構。

+0

謝謝指出! – minjang 2010-03-13 08:08:53