Entwickler-Ecke
C# - Die Sprache - ref this
duckhunter - Mi 26.09.07 17:34
Titel: ref this
Hi Leute,
ich habe vor von VB auf C# umzusteigen. Allerdings habe ich schon ein Problem.
Ich habe eine Root-Klasse. In dieser Root-Klasse befinden sich mehrere "Unterklassen". Ich mochte aber von diesen Unterklassen auf die Eigenschaften der Root-Klasse zugreifen und diese auch verändern können. In VB ging das so.
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
| Module Module1
Sub Main() Dim _Root As New Root() Console.ReadKey() End Sub
Private Class Root
Dim _i As Integer Dim _Unterklasse As Unterklasse
Public Sub New() _i = 5 Console.WriteLine(_i.ToString()) _Unterklasse = New Unterklasse(Me) Console.WriteLine(_i.ToString()) End Sub
Private Class Unterklasse
Public Sub New(ByRef RootKlasse As Root) RootKlasse._i = 10 End Sub
End Class
End Class
End Module |
Hier klappt alles wunderbar. Die Variable _i hat zuerst den Wert 5, dann wird sie über die andere Klasse geändert und hat den Wert 10. Nun das gleiche in C#.
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37:
| using System; using System.Collections.Generic; using System.Text;
namespace ConsoleApplication2 { class Program { static void Main(string[] args) { Root _Root = new Root(); Console.ReadKey(); }
private class Root { int _i; Unterklasse _Unterklasse;
public Root() { _i = 5; Console.WriteLine(_i.ToString()); _Unterklasse = new Unterklasse(ref this); Console.WriteLine(_i.ToString()); }
private class Unterklasse { public Unterklasse(ref Root RootKlasse) { RootKlasse._i = 10; } } } } } |
Hier kommt dann der Fehler:
"<this>" kann nicht als ref- oder out-Argument übergeben werden, da das Element schreibgeschützt ist.
Kann ich das irgendwie umgehen oder gibt es vielleicht sogar eine ellegantere Lösung für das Problem?
mfg und vielen Dank im Voraus
duckhunter
Kha - Mi 26.09.07 19:24
VB kompiliert das? Lol[1].
Eine Übergabe by reference ist hier jedenfalls unnötig, da du der Variablen selbst nichts zuweist, nur eine Eigenschaft änderst. Den ref-Modifier solltest du also einfach so entfernen können.
Noch ein paar Tipps:
- Unterstriche sind böse. Felder- und Parameternamen werden normalerweise mit einem kleinen Buchstaben begonnen.
- Die zwei privates kannst du weglassen, ist bereits der Standard-Modifier für alle Member innerhalb eines Typs.
- Auch wenn - oder gerade weil - das wohl nur ein Beispielcode ist: Nested Types werden äußerst selten benutzt. Sicher, dass du dann auch noch zwei ineinander verschachtelte brauchst ;) ?
[1]Nein, mehr fällt mir dazu wirklich nicht ein.
duckhunter - Mi 26.09.07 19:46
Hmm das versteh ich jetzt nicht ganz, wie sollte ich dann auf die Root-Klasse zugreifen, wenn in dieser was geändert werden muss?
danke für die Hilfe!!
mfg
Kha - Mi 26.09.07 19:50
Wenn meine Erklärung nix taugt, klau ich eben eine aus dem SDK :-B :
Passing Reference-Type Parameters (C# Programming Guide) hat folgendes geschrieben: |
A variable of a reference type does not contain its data directly; it contains a reference to its data. When you pass a reference-type parameter by value, it is possible to change the data pointed to by the reference, such as the value of a class member. However, you cannot change the value of the reference itself; that is, you cannot use the same reference to allocate memory for a new class and have it persist outside the block. To do that, pass the parameter using the ref or out keyword. |
duckhunter - Mi 26.09.07 20:15
Hmmm ... jetzt hab ich alles verstanden *gggg*.
Sorry steh im Moment voll auf der Leitung, kannst du das vllt in einen Source Code oder als Beispiel anführen?
Danke ;)
mfg
Kha - Mi 26.09.07 20:54
Noch einmal: Entferne einfach die zwei ref und dein Programm wird funktionieren.
duckhunter - Mi 26.09.07 21:04
Ahh sehr gut danke.
Aber warum funktioniert es in diesem Fall?
Wenn ich z.B. folgenden Programmcode habe:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41:
| using System; using System.Collections.Generic; using System.Text;
namespace ConsoleApplication2 { class Program { static void Main(string[] args) { Root _Root = new Root(); Console.ReadKey(); }
private class Root { int _i; Unterklasse _Unterklasse;
public Root() { _i = 5; Console.WriteLine(_i.ToString()); _Unterklasse = new Unterklasse(_i); Console.WriteLine(_i.ToString()); }
private class Unterklasse { public Unterklasse(int i) { i = 10; } } } } } |
Wenn ich das so programmiere, dann wird i natürlich nicht 10, außer ich übergebe es so:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| public Root() { _i = 5; Console.WriteLine(_i.ToString()); _Unterklasse = new Unterklasse(ref _i); Console.WriteLine(_i.ToString()); }
private class Unterklasse { public Unterklasse(ref int i) { i = 10; } } |
Warum wird nun die Variable i in der Klasse (ohne der ref-Übergabe) geändert und warum wird i nicht geändert, wenn ich nur die Variable (wie im Codeblock 1) übergebe. Wenn ich mit i mit ref Übergebe (Codeblock 2) funktioniert es logischerweise.
mfg
Edit:
Sry war mein Fehler, jetzt ist alles klar.... Ich habe hier ja nur ein schnelles Beispiel angegeben, was ich in Wirklichkeit für was komplexeres benötige... Naja egal auf jeden Fall jetzt klappt alles, danke nochmal Khabarakh!
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!