Gateway_man Geschrieben 8. Juni 2011 Geschrieben 8. Juni 2011 (bearbeitet) Hi allerseits, folgendes Ereigniss iritiert mich und ich hoffe ihr könnt mir das näher erläutern. Ich habe eine Liste von objekten, welche ich durchschleife. Deren Elemente lasse ich auf diverse Konstelationen prüfen. Sofern diese den Anforderungen entsprechen, werden Sie zur Bearbeitung an eine weitere Klasse weitergegeben (ohne ref etc.). Wenn der Dialog dann zweckmäßig beendet wird, wird das veränderte Objekt einer neuen Liste hinzugefügt. Jedoch verwirt mich das das ursprungsobjekt der Ursprungsliste ebenfalls den geänderten Wert innehält. foreach (ppt.SlideObject item in cSlide.Objects) { if (item.UniqueID == (int)dataGridView1.SelectedRows[0].Cells[1].Value && (Core.MsoShapeType)item.Type == Microsoft.Office.Core.MsoShapeType.msoGroup) { for (int ival =0;ival<=item.Define.GroupShapeCollection.Container.Count - 1;ival++) { if (item.Define.GroupShapeCollection.Container[ival].Define.GroupLink != null && item.Define.GroupShapeCollection.Container[ival].Define.GroupLink.GroupUniqueID == (int)dataGridView1.SelectedRows[0].Cells[1].Value && item.Define.GroupShapeCollection.Container[ival].ID == (int)dataGridView1.SelectedRows[0].Cells[0].Value) { el.obj = item.Define.GroupShapeCollection.Container[ival]; if (el.ShowDialog() == DialogResult.OK && el.hChanged) { ppt.RevSlideObject xobj = new pptdispatcher.ppt.RevSlideObject(el.obj); xobj.TempName = "TempRev" + (refobjects.Count + 1).ToString() + " " + xobj.Name; xobj.VirtualID = "v" + (virtualidcounter++).ToString(); xobj.ID = id; refobjects.Add(xobj); object[] row = new object[4]; row[0] = xobj.VirtualID; row[1] = false; row[2] = xobj.TempName; row[3] = "-----------"; dataGridView2.Rows.Add(row); } break; } } break; } } Kleineres Beispiel anhand von PseudoCode: String Stringliste Für jedes Stringelement in Stringliste BEGIN String lokalerstring = Stringelement WENN lokalerstring gleich "Test123" BEGIN lokalerstring = "Fertig" //Wird dieser Wert verändert wird auch das Stringelement in der Liste entsprechend verändert. //Meine Frage also: Warum wird hier referenziert und wie kann ich das verhindert? END END lg Gateway Bearbeitet 8. Juni 2011 von Gateway_man Zitieren
Guybrush Threepwood Geschrieben 8. Juni 2011 Geschrieben 8. Juni 2011 Wenn du den Wert in einem Referenz Typen änderst wirkt sich das logischerweise immer auch auf das übergebene Objekt aus. PS: http://msdn.microsoft.com/en-us/library/s6938f28.aspx Zitieren
Gateway_man Geschrieben 8. Juni 2011 Autor Geschrieben 8. Juni 2011 Ich nutze kein ref schlüsselwort also ist mir auch nicht klar wo da referenziert wird oder wo da der ein Referenztyp ist? Das hat er doch vorher auch nicht getan. Zitieren
Guybrush Threepwood Geschrieben 8. Juni 2011 Geschrieben 8. Juni 2011 Objekte sind immer Referenzdatentypen das hat nichts mit dem ref Schlüsselwort zu tun. Das ist ganz normales Verhalten das schon immer und in jeder ähnlichen Sprache so war Zitieren
Gateway_man Geschrieben 8. Juni 2011 Autor Geschrieben 8. Juni 2011 Warum ist das dann bei folgendem kleinen vb beispiel nicht so? Dim list As List(Of Object) = New List(Of Object) list.Add("test1") list.Add("test2") For Each item As Object In list Dim localstring as Object = item If localstring = "test1" Then localstring = "x1" End If Next Der Wert des ersten Elements in der Liste bekommt nicht den wert x1. Das ist genau die selbe konstelation (nur vereinfacht) wie in meiner C Sharp Routine. der wert des localstrings wird auf x1 gesetzt werden der Wert des Objects Item weiterhin "test1" lautet. lg Gateway Zitieren
Guybrush Threepwood Geschrieben 8. Juni 2011 Geschrieben 8. Juni 2011 (bearbeitet) Ich sagte in "jeder ähnlichen Sprache", VB ist...nunja anders Außerdem ist das Beispiel nicht das Selbe. Du hast keinen Funktionsaufruf und erstellst eine Kopie des Strings. Bearbeitet 8. Juni 2011 von Guybrush Threepwood Zitieren
Gateway_man Geschrieben 8. Juni 2011 Autor Geschrieben 8. Juni 2011 Da stimmt was nicht. Denn wenn ich mit C# selbiges Beispiel durchgehe erhalte ich genau das selbe verhalten wie bei vb.net. List<object> list = new List<object>(); list.Add("test1"); list.Add("test2"); foreach (object item in list) { object localstring = item; if (localstring == "test1") { localstring = "x1"; } } Und zwar exakt das selbe. Sprich es scheint wohl doch nicht referenziert zu werden in diesem Fall. Das würde mich auch wundern da mir so etwas schon früher aufgefallen wäre, da ich nicht erst seit gestern mit C# arbeite. Umso mehr wundert mich das Ereigniss im ersten Post, da ich wie gesagt das selbe Schema verfolge. lg Gateway Zitieren
Guybrush Threepwood Geschrieben 8. Juni 2011 Geschrieben 8. Juni 2011 Ja weil das Beispiel nicht das selbe macht wie der Code in deinem Ursprungspost. Hast du den Link gelesen den ich oben gepostet habe? Da wird das eigentlich ganz genau erklärt... Zitieren
Gateway_man Geschrieben 8. Juni 2011 Autor Geschrieben 8. Juni 2011 hi, sry steh hier echt aufm Schlau :old. Weder übergebe ich das Objekt einer Funktion mit einem ref Schlüsselwort oder definiere dieses in einer anderen Funktion neu. Gibts keinen Befehl mit dem ich ein Objekt gänzlich kopiere? Ich versteh grad nur Bahnhof. Das es bei Übergabeparametern prinzipiell zwei möglichkeiten gibt war mir schon bewusst. Aber das betrifft mich doch nicht da ich nichtmal einene Funktion aufrufe. Daher versteh ich jetzt den Zusammenhang mit der msdn Seite nicht ganz. Ich hab das mal eingegrenzt und den Wert Manuel geändert noch in der Foreach schleife mit dem selben irritierenden Ergebniss. foreach (ppt.SlideObject subitem in item.Define.GroupShapeCollection.Container) { if (subitem.Define.GroupLink != null && subitem.Define.GroupLink.GroupUniqueID == (int)dataGridView1.SelectedRows[0].Cells[1].Value && subitem.ID == (int)dataGridView1.SelectedRows[0].Cells[0].Value) { //System.Runtime.InteropServices.Marshal.cop ppt.SlideObject cobj = subitem; cobj.Define.TxTFrame.Value = "test"; //Auch hier wird ebenfalls der Wert des subitems auf test! //Ich versteh nurnoch Bahnhof break; } } Zitieren
Guybrush Threepwood Geschrieben 8. Juni 2011 Geschrieben 8. Juni 2011 Aber das betrifft mich doch nicht da ich nichtmal einene Funktion aufrufe. Daher versteh ich jetzt den Zusammenhang mit der msdn Seite nicht ganz. Da du oben schriebst das du es ohne ref übergibst bin ich davon ausgegangen das du es einer Methode einer anderen Klasse übergibst. Das Prinzip ist aber trotzdem das Selbe. namespace ConsoleApplication1 { class Program { static void Main(string[] args) { A a = new A(); a.str = "Hello"; B b = new B(); b.value = a; b.value.str = "World"; Console.WriteLine("{0} {1}!", a.str, b.value.str); } } class A { public string str; } class B { public A value; } } [/PHP] Gibt [i]World World![/i] aus weil hier b.value = a; b.value eine Referenz auf a zugewiesen wird da Klassen immer Referenzdatentypen sind. Wenn man das nicht will muss man das Objekt kopieren. Eine Möglichkeit dazu wäre Serialisieren und wieder Deserialisieren oder zum Beispiel IClonable zu implementieren: [PHP] namespace ConsoleApplication1 { class Program { static void Main(string[] args) { A a = new A(); a.str = "Hello"; B b = new B(); b.value = a.Clone() as A; b.value.str = "World"; Console.WriteLine("{0} {1}!", a.str, b.value.str); } } class A : ICloneable { public string str; #region ICloneable Members public object Clone() { return this.MemberwiseClone(); } #endregion } class B { public A value; } } Wenn eine flache Kopie nicht ausreichen sollte muss man dann halt in der Clone Methode die entsprechenden Member manuell kopieren. Zitieren
Gateway_man Geschrieben 8. Juni 2011 Autor Geschrieben 8. Juni 2011 So hat sich nun herrausgestellt das sich diese Klasse sich nicht "Klonnen" lässt . Ist mir bissher nie so richtig aufgefallen, aber mir hat diese Seite sehr geholfen. Ich muss sagen ich kann diese engen Regeln des .NET nicht ganz nachvollziehn. In anderen Sprachen ist man dahingehend doch etwas freier. Zitieren
Guybrush Threepwood Geschrieben 8. Juni 2011 Geschrieben 8. Juni 2011 Welche Sprachen sollen das denn sein? Zitieren
Gateway_man Geschrieben 8. Juni 2011 Autor Geschrieben 8. Juni 2011 ADA . Nicht gerade weit verbreitet (leider). Zitieren
lilith2k3 Geschrieben 8. Juni 2011 Geschrieben 8. Juni 2011 Was hier Verwirrung stiftet ist der Unterschied zwischen call by reference und call by value, welches man in anderen Sprachen kennt und dem signifikanten Unterschied zwischen Werttypen und Referenztypen in C#. Was Du im Sinn hast ist erstere Unterscheidung. In der Regel erfolgt bei C# eine Übergabe als call by value. Das hat aber folgenden Effekt: Wird ein Werttyp übergeben wird innerhalb der Funktion mit einer Kopie der Werttypen gearbeitet. Das Verhalten, was man im Grunde auch von call by value erwartet. Wird ein Referenztyp übergeben, so wird auch dieser "Wert" kopiert - also reguläres call by value-Verhalten. Der Haken an der Sache ist, dass es sich eben lediglich um die Kopie der Referenz und nicht um eine Kopie des referenzierten Objekts handelt. C# verhält sich ganz konsistent, aber für den unbedarften Nutzer kontraintuitiv. Rapid Application Development: Parameter passing in C# erklärt die Zusammenhänge sehr gut. Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.