2010-03-13 16 views
5

Ich bin ein C++ Experte, aber überhaupt nicht für C#. Ich habe eine Dictionary<string, STATS> erstellt, wobei STATS eine einfache struct ist. Sobald ich das Wörterbuch mit den ursprünglichen string und STATS Paaren gebaut habe, möchte ich den STATS Wert des Wörterbuchs ändern. In C++, es ist ganz klar:Ändern C# -Wörterbuch Wert

Dictionary<string, STATS*> benchmarks; 
Initialize it... 

STATS* stats = benchmarks[item.Key]; 
// Touch stats directly 

Allerdings habe ich versucht, wie dies 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. 
} 

Dies ist ein wirklich Anfänger Problem ist, aber es war nicht einfach, eine Antwort zu finden.

EDIT: Ich habe auch versucht, wie die folgenden:

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

Allerdings habe ich die Ausnahme bekam, da eine solche Aktion Wörterbuch entkräftet:

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

Ugh, du hättest diese Großbuchstaben in der C++ Welt zurücklassen sollen. Es sieht in C# schrecklich aus. Die Benennungsrichtlinien von Microsoft schlagen vor, Pascal-Fall zu verwenden. –

+0

Eine Struktur ist ein Werttyp, daher ist dies derselbe, der dann ein lokales Doppel deklariert, daher ist das neue stat_item eine Kopie des Wörterbuchsatzes. Wenn STATS eine Klasse wäre, dann wäre es eine Referenz und dann würde es funktionieren. – weismat

+0

Dies ist ein sehr einfaches Spielzeug-Parsing-Programm. : D Eigentlich schreibe ich immer noch gerne Code im Windows C++ Stil, aber jetzt muss ich der Google-Richtlinie folgen ... Entschuldigung dafür! – minjang

Antwort

10

wenn Ihre STATS in der Tat ist ein struct, das heißt, es ist ein Werttyp, also wo Sie dies tun:

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

Ihre stat_item ist ein Kopie des Wertes bei benchmarks[item.Key] entfernt. Wenn Sie es also als ref Parameter an ParseOutputFile übergeben, wird nur die Kopie geändert.

In dem C++ - Code, den Sie gepostet haben, beachten Sie, dass Sie mit einem Zeiger versuchen würden, was Sie hier erreichen möchten.

Für .NET ist die Lösung einfach: Änderung STATS zu einem Referenztyp (a class statt struct). Dann ist Ihre lokale Variable eine Referenz auf das gleiche Objekt, auf das der Wert benchmarks[item.Key] verweist.

+0

Danke, es funktioniert einfach gut. Ich kannte solche Semantik nicht. – minjang

0
diese

Versuchen:

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

Beachten Sie, dass selbst wenn STATS eine Klasse ist, dann aktualisieren Die Referenz (wie durch das Schlüsselwort ref angegeben) aktualisiert nur die lokale Referenz stat_item, nicht den Wert im Wörterbuch.

Zum Beispiel der folgende Code den Wert im Wörterbuch ändern, wenn STATS eine Klasse (aber in diesem Fall ist das Schlüsselwort ref ist nicht erforderlich und sollte entfernt werden) ist:

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

Aber die folgende Wille nur die lokale Variable beeinflussen und nicht im Wörterbuch Wert aktualisieren, selbst wenn STATS eine Klasse:

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

Sie sollten STATS einfach in eine Klasse ändern. Dann würden Sie das Schlüsselwort ref nicht benötigen und das Objekt würde sich ändern.

Der übliche Ratschlag in C# ist die Verwendung von Klassen, es sei denn, Sie sind absolut sicher, dass Sie benötigen eine Struktur.

+0

Vielen Dank für das Hinweis! – minjang