PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : HashCode und Sets


Monger
2007-07-16, 10:34:52
Ich hätte da ein paar Fragen was den richtigen Umgang mit Collections angeht.


Erstens:
ich kenne aus Java die "Set" Klasse aus dem Collections Framework. Gibt es dazu irgendein Äquivalent in .NET? oder behilft man sich da einfach mit einem Dictionary, was halt nur Schlüssel und keine Values hat.

Zweitens:
Ich hab zu dem Thema einiges gelesen, hab es aber bis heute nicht verstanden - wie genau sollte ich die hashCode() Methode überschreiben?
Ich hab so im Kopf, dass Objekte die gleich sind, auch die selben Hashwerte haben sollten. Und Hash Tables suchen ihre Objekte ja anhand ihres HashCodes.
Was passiert aber, wenn sich das Objekt ändert? Soll sich dann auch der Hashwert ändern?
Findet dann eine Hashtable überhaupt das Objekt noch wieder?

Bietchiebatchie
2007-07-16, 11:21:05
Erstens:
ich kenne aus Java die "Set" Klasse aus dem Collections Framework. Gibt es dazu irgendein Äquivalent in .NET? oder behilft man sich da einfach mit einem Dictionary, was halt nur Schlüssel und keine Values hat.

Im .Net-Framework 3.5 gibts eine Klasse Set oder HashSet, dummerweise hab ich aber auch bei msdn nix gefunden... vielleicht noch nicht dokumentiert.
Warum die erst jetzt dazugekommen ist, weiß auch nur MS.
Falls du unter 3.0 oder früher benutzt, bau einfach nen wrapper um eine normales Dictionary.


Zweitens:
Ich hab zu dem Thema einiges gelesen, hab es aber bis heute nicht verstanden - wie genau sollte ich die hashCode() Methode überschreiben?
Ich hab so im Kopf, dass Objekte die gleich sind, auch die selben Hashwerte haben sollten. Und Hash Tables suchen ihre Objekte ja anhand ihres HashCodes.
Was passiert aber, wenn sich das Objekt ändert? Soll sich dann auch der Hashwert ändern?
Findet dann eine Hashtable überhaupt das Objekt noch wieder?

1. Bei Reference-Types überschreibt man die GetHashcode-Methode grundsätzlich nie... außer du hast nen richtig guten Grund dafür. Der Hashcode bleibt gleich, wenn sich das Object verändert(da die Adresse ja auch gleich bleibt).

2. Bei Value-Types musst du eine adäquate Mehtode implementieren. Wichtig ist, dass x.GetHashCode() = y.GetHashCode() genau dann wenn x.Equals( y ). Standardmäßig ist der Rückgabewert der Hashwert des ersten Feldes.
Da Value-Types ja grundsätzlich immutable sein sollen, erledigt sich auch die Frage, was passiert, wenn sich das Object ändert. Falls das Object doch nicht immutable ist(da z.B. super-simple Klasse à la Vector2D) ist der Hashcode auch veränderbar, je nach Zustand des Objektes.

SGT.Hawk
2007-07-16, 13:29:08
Nein, du erzählst was falsches!
Man darf, nachdem man Objekte in einer Hasmap eingefügt hat, das Objekt selbst nicht mehr verändern, das sollte man immer im Hinterkopf behalten, sonst findet man das Objekt nicht mehr, da ja auch der Hashcode sich geändert hat, daher hast du dann Leichen....
Auch die hascode bei Refernz Typen MUSS man geiegnet überschrieben, da die Standard Implemntierunf nur Adresse als Hashwert nimmt, dies ist aber nicht immer gewünscht, fallls man bei Gleichheit eine andere semantische Bedeutung haben will.

Bietchiebatchie
2007-07-16, 14:43:29
Nein, du erzählst was falsches!

Aha, mal schauen ;)

Man darf, nachdem man Objekte in einer Hasmap eingefügt hat, das Objekt selbst nicht mehr verändern, das sollte man immer im Hinterkopf behalten, sonst findet man das Objekt nicht mehr, da ja auch der Hashcode sich geändert hat, daher hast du dann Leichen....

Der HashCode bleibt bei Reference-Types grundsätzlich gleich... daher darf sich das (Reference)-Object ja auch ändern (da die Adresse gleich bleibt).
Oder anders gesagt: Deine Argumentation ist genau der Grund, warum man den HashCode bei Ref-Types nicht überschreiben soll.


Auch die hascode bei Refernz Typen MUSS man geiegnet überschrieben, da die Standard Implemntierunf nur Adresse als Hashwert nimmt, dies ist aber nicht immer gewünscht, fallls man bei Gleichheit eine andere semantische Bedeutung haben will.
Nicht immer? Naja, da es relativ schwierig (oder besser gesagt: in manchen Fällen nahezu unmöglich) ist, zu sagen wann ein Refernce-Objekt semantisch(!) gleich einem anderen ist, begnügt man sich i.d.R. damit dass x.Equals( y ) <=> Adresse von x = Adresse von y.

Wie oben schon erwähnt: Equals(_) genau dann überschreiben, wenn man GetHashCode() überschreibt. Ich hab das häufig so gemacht, dass ich in GetHashCode eine NotSupportedException geworfen habe, wenn ich Equals überschreiben wollte, aber keine gute Grundlage hatte um den Hashcode zu berechnen. Ist natürlich nur ein Workaround, aber funktioniert.

Monger
2007-07-16, 14:59:37
Wie oben schon erwähnt: Equals(_) genau dann überschreiben, wenn man GetHashCode() überschreibt.

Ich glaube, das ist mein entscheidendes Mißverständnis. Ich dachte, ich sollte zwingend hashCode überschreiben, wenn ich bereits equals überschrieben habe.
Wenn ich dich jetzt richtig verstanden habe, muss das aber nicht unbedingt sein, oder?
Weil eine Hashtable o.ä. setzt voraus, dass der Hashcode eines Objektes sich nie ändert, während "equals" nur garantiert, dass beide Objekte sich gerade im Moment des Aufrufs gleichen.

Wieso sollte ich denn überhaupt hashCode überschreiben wollen? Nur, um bei immutablen Datentypen viele Schlüssel in hashbasierten Strukturen zu vermeiden, oder?

Bietchiebatchie
2007-07-16, 15:10:26
Ich glaube, das ist mein entscheidendes Mißverständnis. Ich dachte, ich sollte zwingend hashCode überschreiben, wenn ich bereits equals überschrieben habe.

Äh ja, genau dass sage ich doch: equals überschreiben => hashcode auch (und umgekehrt).


Wenn ich dich jetzt richtig verstanden habe, muss das aber nicht unbedingt sein, oder?
Nein, s.o.


Weil eine Hashtable o.ä. setzt voraus, dass der Hashcode eines Objektes sich nie ändert, während "equals" nur garantiert, dass beide Objekte sich gerade im Moment des Aufrufs gleichen.
Für Reference-Types ja: hashcode soll gleich bleiben (daher nicht überschreiben ;) )
Für Value-Types: du kriegst doch eh immer eine Kopie zurück beim Zugriff auf ein Dictionary (oder Set oder whatever), d.h. du kannst das Objekt im Dictionary gar nicht ändern!


Wieso sollte ich denn überhaupt hashCode überschreiben wollen?
Warum willst du unbedingt Equals überschreiben? ;)
Nur, um bei immutablen Datentypen viele Schlüssel in hashbasierten Strukturen zu vermeiden, oder?
Das versteh ich gerade nich, sorry.

Bietchiebatchie
2007-07-16, 15:22:47
Für Value-Types: du kriegst doch eh immer eine Kopie zurück beim Zugriff auf ein Dictionary (oder Set oder whatever), d.h. du kannst das Objekt im Dictionary gar nicht ändern!

Eigentlich überlege ich gerade, ob das überhaupt stimmt... hmpf.

Nee, das is falsch: du kriegst schon das konkrete Value-Objekt zurück. Und genau deshalb ist eine Grundvorschrift für Value-Types, die auch in Dictionaries benutzt werden sollen: Immutable machen.

Monger
2007-07-16, 15:25:48
Edit: hat sich erledigt. Du hast es ja selbst zurückgezogen.

Warum willst du unbedingt Equals überschreiben? ;)

Damit ich zwei Objekte vergleichbar machen kann. Was aber hashCode wirklich macht/machen soll (bzw. wozu ich es brauche), ist mir eben immer noch unklar.

Bietchiebatchie
2007-07-16, 15:29:22
Was, ernsthaft? Da wird eine tiefe Kopie gemacht?!?
Jetzt mal angenommen ich mach sowas:

MeinObjekt obj = new MeinObjekt();
Dictionary dict = new Dictionary(of MeinObjekt, Object);

dict.add(obj, null);
obj.value = "Blablabla"

dann ändert sich das im Dictionary nicht ?!?

äh zuerst: s.o. meine Korrektur.
ansonsten falls MeinObjekt ein Ref-Type: natürlich.
falls MeinObject ein Value-Type ist: natürlich nicht.


Damit ich zwei Objekte vergleichbar machen kann. Was aber hashCode wirklich macht (bzw. wozu ich es brauche), ist mir eben immer noch unklar.
Die Frage ist nicht, was GetHashCode macht, sondern was es denn deiner Meinung nach machen soll.
Vorschlag: Wie wäre es damit: in Equals(x) steht doch sicherlich sowas wie return this.Bla == x.Bla (o.ä.)
dann bei HashCode: return this.Bla.GetHashCode.

Xmas
2007-07-16, 20:46:09
1. Bei Reference-Types überschreibt man die GetHashcode-Methode grundsätzlich nie... außer du hast nen richtig guten Grund dafür. Der Hashcode bleibt gleich, wenn sich das Object verändert(da die Adresse ja auch gleich bleibt).
Erst einmal unterscheiden: GetHashCode ist .Net, hashCode ist Java. Die Standardimplementierung von letzterem nutzt die Adresse an der das Objekt angelegt wurde als Hashwert (die tatsächliche Adresse kann sich aber bei einem Compacting Garbage Collector ändern). GetHashCode tut dies soweit ich weiß nicht (ein compacting GC ist bei .Net eh Standard).

Dass man Objekte einer Klasse anhand ihres Inhalts vergleichen will kommt eigentlich recht häufig vor. Von daher ist das Überschreiben von hashCode/GetHashCode (und natürlich auch equals) sicher keine seltene Ausnahme, sondern eigentlich ganz normal.

2. Bei Value-Types musst du eine adäquate Mehtode implementieren. Wichtig ist, dass x.GetHashCode() = y.GetHashCode() genau dann wenn x.Equals( y ). Standardmäßig ist der Rückgabewert der Hashwert des ersten Feldes.
"Genau dann" stimmt nicht. Objekte die laut Equals gleich sind sollen denselben Hashcode haben, aber Objekte die denselben Hashcode haben sind noch lange nicht gleich.

Da Value-Types ja grundsätzlich immutable sein sollen, erledigt sich auch die Frage, was passiert, wenn sich das Object ändert. Falls das Object doch nicht immutable ist(da z.B. super-simple Klasse à la Vector2D) ist der Hashcode auch veränderbar, je nach Zustand des Objektes.
Eigentlich überlege ich gerade, ob das überhaupt stimmt... hmpf.

Nee, das is falsch: du kriegst schon das konkrete Value-Objekt zurück. Und genau deshalb ist eine Grundvorschrift für Value-Types, die auch in Dictionaries benutzt werden sollen: Immutable machen.
Warum sollen Value-Types grundsätzlich immutable sein? Value-Types werden immer kopiert, warum sollte man sie immutable machen?

Bietchiebatchie
2007-07-16, 21:22:53
Erst einmal unterscheiden: GetHashCode ist .Net, hashCode ist Java.

Hab mich nur auf .net bezogen. Bezüglich java kann ich nicht wirklich mitreden(was sprachen-/libraries und implementierungsdetails angeht).

Die Standardimplementierung von letzterem nutzt die Adresse an der das Objekt angelegt wurde als Hashwert (die tatsächliche Adresse kann sich aber bei einem Compacting Garbage Collector ändern). GetHashCode tut dies soweit ich weiß nicht (ein compacting GC ist bei .Net eh Standard).

Ja, ok Adresse ist nicht ganz richtig. Soweit ich mich richtig erinnere, nutzt .net intern einen Counter für Instanzen von Klassen und das ist dann der Hashcode. (Korrigiere mich bitte, falls ich da falsch liege, Xmas). Allerdings empfand ich das in dem Kontext ziemlich irrelevant, da ja nur von Interesse wenn der Speicher aufgeräumt und ggf. zusammengefasst wird. (Meinst du das mit "Compacting GC?" ). Daher hab ich der Einfachheit halber von Adressen gesprochen.


Dass man Objekte einer Klasse anhand ihres Inhalts vergleichen will kommt eigentlich recht häufig vor. Von daher ist das Überschreiben von hashCode/GetHashCode (und natürlich auch equals) sicher keine seltene Ausnahme, sondern eigentlich ganz normal.

Hmm ok, da muss ich einfach sagen, dass ich andere Erfahrungen gemacht habe. Liegt wohl daran, dass ich anstatt Equals zu überschreiben, lieber im Clientcode direkt dass abfrage, was andere dann in Equals packen.
(Ok, ich hab glaube ich Probleme mit Equals... Beispiel gefällig: sind zwei System.Windows.Forms.WebBrowser gleich? :devil: ).


"Genau dann" stimmt nicht. Objekte die laut Equals gleich sind sollen denselben Hashcode haben, aber Objekte die denselben Hashcode haben sind noch lange nicht gleich.

Joa, einigen wir uns auf: ist besser wenn sie verschiedenen Hashcode haben, aber nicht zwingend notwendig(besser, da sie dann nicht zwangsläufig im gleichen Hashbucket landen)



Warum sollen Value-Types grundsätzlich immutable sein? Value-Types werden immer kopiert, warum sollte man sie immutable machen?
Bezüglich des immer kopiert: das hab ich ja anfangs auch geschrieben, s.o. Nur was ich mir vorstellen kann, ist das aus Performancegründen nicht garantiert ist, dass du wirklich eine Kopie bekommst, sondern dass u.U. auf das (Value-)Objekt zugegriffen wird. Das ist aber jetzt echt reine Spekulation... Ansonsten finde ich mutable structs irgendwie seltsam; man ändert das Objekt, aber interessieren tut das keine Sau sozusagen ;)

Falls es eben doch nicht kopiert wird, kann folgendes schiefgehen:
Sei V Value-Type.
V v;
v.Foo = bla;
List<V> list;
list.Add(v);
list[0].Foo = blubb;

OT: Kann man sich irgendwo anschauen, wie oft man einen Beitrag schon editiert hat?^^

Xmas
2007-07-16, 22:53:42
Joa, einigen wir uns auf: ist besser wenn sie verschiedenen Hashcode haben, aber nicht zwingend notwendig(besser, da sie dann nicht zwangsläufig im gleichen Hashbucket landen)
Wie jetzt, Objekte die semantisch gleich sind sollen unterschiedliche Hashcodes bekommen?

Bezüglich des immer kopiert: das hab ich ja anfangs auch geschrieben, s.o. Nur was ich mir vorstellen kann, ist das aus Performancegründen nicht garantiert ist, dass du wirklich eine Kopie bekommst, sondern dass u.U. auf das (Value-)Objekt zugegriffen wird. Das ist aber jetzt echt reine Spekulation... Ansonsten finde ich mutable structs irgendwie seltsam; man ändert das Objekt, aber interessieren tut das keine Sau sozusagen ;)
Es ist garantiert dass sich das Programm so verhält als ob es eine Kopie bekäme. Wären sie nicht mutable, müsste man ja selbst innerhalb eines Stackframes ständig kopieren, wenn man gerade mal einen Wert in einer struct ändern will.

Bietchiebatchie
2007-07-17, 08:34:48
Wie jetzt, Objekte die semantisch gleich sind sollen unterschiedliche Hashcodes bekommen?

Hmm? Nein, natürlich nicht... wo schreib ich sowas?
Meine Antwort bezog sich auf den letzten Teil: Objekte, die nicht Equals sind, dürfen gleichen Hashcode haben.


Es ist garantiert dass sich das Programm so verhält als ob es eine Kopie bekäme.

Ok. Dann hatte ich eben unsinnige Befürchtungen, was Optimierung angeht.


Wären sie nicht mutable, müsste man ja selbst innerhalb eines Stackframes ständig kopieren, wenn man gerade mal einen Wert in einer struct ändern will.

Ok, jetzt hast du mich da, wo ich eigentlich ungern stehe, nämlich bei einer doch relativ weit Begründung:
Um es spannend zu machen ( ;) ) : Kannst du dir ein Problem vorstellen, wenn ein mutable Value-Type boxed wird?

Ectoplasma
2007-07-17, 09:05:55
Was aber hashCode wirklich macht/machen soll (bzw. wozu ich es brauche), ist mir eben immer noch unklar.

Der Hash Code hat in Hash Sets die Aufgabe eine gute Verteilung der Werte in dem Hash Set zu erreichen. Ist der Bereich in dem sich ein Hash-Wert ändert gering, kann es zu Kollisionen an einem Speicherort in dem Hash-Set kommen, die meist durch eine verkettete Liste aufgelöst werden. Und das mindert die Performance. Eine gute Hash-Code Implementierung hat einzig die Aufgabe, die Performance zu steigern. Zumindest in Container-Klassen, die mit einem Hash-Code arbeiten.

Xmas
2007-07-17, 14:42:13
Ok, jetzt hast du mich da, wo ich eigentlich ungern stehe, nämlich bei einer doch relativ weit Begründung:
Um es spannend zu machen ( ;) ) : Kannst du dir ein Problem vorstellen, wenn ein mutable Value-Type boxed wird?
Ich sehe da eigentlich keine Probleme, höchstens ein Verständnisproblem.

SGT.Hawk
2007-07-19, 01:46:52
1. Java kann man keine Value-Typen in Container packen,nur Objekte.
Gerade, wenn man Set oder Hashset benutzt, MUSS man die Standardimplemetierung oveririden, sonst findet man seine Pbjekte nicht mehr, denn die Prüfung auf die Identität ist nicht richtig, denn sonst könnte man ja ein semantisch gleiches Objekt zweimal in einem Set haben, was falsch ist, deswegen soll man ja gerade equals für Sets und zusätzlich bei Dictionaries oder Hash den hashcode overriden.
PS:Bitchiebabe, du bringst einiges durcheinander in Java.

Bietchiebatchie
2007-07-19, 10:59:02
Hab mich nur auf .net bezogen. Bezüglich java kann ich nicht wirklich mitreden(was sprachen-/libraries und implementierungsdetails angeht).

Hast du das auch gelesen?

Bietchiebatchie
2007-07-19, 11:23:22
Gerade, wenn man Set oder Hashset benutzt, MUSS man die Standardimplemetierung oveririden, sonst findet man seine Pbjekte nicht mehr, denn die Prüfung auf die Identität ist nicht richtig, denn sonst könnte man ja ein semantisch gleiches Objekt zweimal in einem Set haben, was falsch ist, deswegen soll man ja gerade equals für Sets und zusätzlich bei Dictionaries oder Hash den hashcode overriden.

Wenn die Überprüfung mittels Identität nicht richtig ist, handelt es sich um ein semantisches Value-Objekt. Semantisches Value-Objekt heißt, dass ein Objekt nicht durch seine Identität sondern einzig und allein durch seinen Zustand gekennzeichnet ist. (Beispiele hierfür: DateTime, Color, ...). Semantische Value-Objekte müssen nicht zwangsläufig structs in .net sein..

Falls du deine Aussage oben nun auf semantische Value-Objekte bezogen hast, stimme ich dir zu. Für "echte" Reference-Objekte reicht der Identitätscheck.

Ich glaube, dass Hauptproblem, was du mit meinen Aussagen hast, ist dass ich mich auf .net beziehe und gerade in Bezug auf Reference/Value-Types unterscheiden sich eben java und .net doch schon voneinander, da man eben in java keine "echten" Value-Types implementieren kann.

TheGamer
2007-07-19, 14:07:58
einem Dictionary, was halt nur Schlüssel und keine Values hat

Ein Dictionary hat Keys und Values

Bietchiebatchie
2007-07-19, 14:10:55
Er meint ein Dictionary, wo unter den Keys ein beliebiger Value abgespeichert wird, da der Value eh uninteressant ist.

Xmas
2007-07-19, 14:21:53
Ok, jetzt hast du mich da, wo ich eigentlich ungern stehe, nämlich bei einer doch relativ weit Begründung:
Um es spannend zu machen ( ;) ) : Kannst du dir ein Problem vorstellen, wenn ein mutable Value-Type boxed wird?
Kommt dazu noch eine Erklärung?

Bietchiebatchie
2007-07-19, 14:38:55
Kommt dazu noch eine Erklärung?
Sorry, aber ich hatte das

Ich sehe da eigentlich keine Probleme, höchstens ein Verständnisproblem.

so interpretiert, dass du das Problem als nicht relevant empfindest.

Erklärung siehe http://onezero.org/blog/archives/13 ganz unten.
Wie gesagt, kann man als vollkommen irrelevant abtun; mir reichts sowas als Begründung , da es so eine Sache ist, die einen u.U. ewig lang aufhält, da man nicht weiß, wo der Fehler ist.

Xmas
2007-07-19, 15:35:59
Erklärung siehe http://onezero.org/blog/archives/13 ganz unten.
Wie gesagt, kann man als vollkommen irrelevant abtun; mir reichts sowas als Begründung , da es so eine Sache ist, die einen u.U. ewig lang aufhält, da man nicht weiß, wo der Fehler ist.
Ich tue das nicht als irrelevant ab, sondern als falsch. Wie gesagt, Verständnisproblem.

Eine Boxed-Instanz ist ja ausschließlich durch die Methoden eines Interface mutable. Wenn ich aber eine Interface-Variable habe, sehe ich dieser gar nicht an ob sie eine Boxed-Instanz oder ein "echtes" Referenztypobjekt beinhaltet. Wenn ich aber ein Interface habe das Methoden anbietet um die Instanz zu verändern, dann erwarte ich doch wohl, dass das Aufrufen der Methode das durch die Interfacevariable referenzierte Objekt verändert.

Eine Boxed-Instanz existiert auf dem Heap, wird über Referenzen angesprochen und vom GC beseitigt wenn sie nicht mehr benötigt wird. Sie ist, mit Ausnahme von typeof/GetType, ein Referenztyp.

Und wenn ich dann das hier sehe ...
void threadSafeMethod(mutableStruct s)
{
mutableStruct t = s;
(work with t)
}
... kann ich nur noch den Kopf schütteln. Von Call-by-Value hat der Mensch wohl noch nie etwas gehört. s ist bereits eine Kopie! Für Call-by-Reference müsste man auf beiden Seiten explizit das ref-Keyword verwenden.

Bietchiebatchie
2007-07-19, 15:48:59
Ich tue das nicht als irrelevant ab, sondern als falsch. Wie gesagt, Verständnisproblem.

Eine Boxed-Instanz ist ja ausschließlich durch die Methoden eines Interface mutable. Wenn ich aber eine Interface-Variable habe, sehe ich dieser gar nicht an ob sie eine Boxed-Instanz oder ein "echtes" Referenztypobjekt beinhaltet. Wenn ich aber ein Interface habe das Methoden anbietet um die Instanz zu verändern, dann erwarte ich doch wohl, dass das Aufrufen der Methode das durch die Interfacevariable referenzierte Objekt verändert.


Da ist die Methodenname "Change" schlecht gewählt. Hieße dieser z.B. "CreateFoo" (mit Rückgabetyp Foo) so würdest du wohl nicht erwarten, dass sich das Objekt ändert, oder?
Bzw. was aus dem Beispiel nicht klar wird: Das boxed-Objekt kann in irgendeiner Funktion verändert werden; während das ja für value-types prinzipiell unmöglich ist.

void threadSafeMethod(mutableStruct s)
{
mutableStruct t = s;
(work with t)
}
Das ist Bullshit, keine Ahnung was das soll.
Edit: eine Idee was er meinen könnte: verschiedene Threads greifen auf selbe lokale Variable zu:

ValueType vt;
new Thread( () => vt.Foo = lalala).Start();
new Thread( () => vt.Foo = lalala2).Start();

Dann ist das Beispiel aber selten dämlich.



Abgesehen davon: Du machst structs nicht zwangsläufig immutable, ich schon; selbst wenn wir zusammen an einem Projekt arbeiten, wird dass höchstwahrscheinlich genau null Probleme verursachen.

Xmas
2007-07-19, 16:06:42
Da ist die Methodenname "Change" schlecht gewählt. Hieße dieser z.B. "CreateFoo" (mit Rückgabetyp Foo) so würdest du wohl nicht erwarten, dass sich das Objekt ändert, oder?
Wenn ich eine Interfacevariable benutze (oder ein Object in ein Interface caste), dann erwarte ich dass sich das Objekt wie ein Referenztyp verhält. Egal wie die Methode heißt.

int foo(IBar x)
{
x.setValue(1);
return x.getValue();
}
Erwartest du hier etwa unterschiedliches Verhalten, abhängig davon ob x eine Boxed-Instanz oder eine "echte" Referenztypinstanz ist? Aus welchem Grund sollte ich denn glauben dass eine Boxed-Instance immutable ist? Weil irgendjemand ohne nachzudenken diesen Quatsch im Internet verbreitet?

Abgesehen davon: Du machst structs nicht zwangsläufig immutable, ich schon; selbst wenn wir zusammen an einem Projekt arbeiten, wird dass höchstwahrscheinlich genau null Probleme verursachen.
Höchstwahrscheinlich nicht. Ich sehe nur keinen Grund, den Anwendungsbereich von structs künstlich zu beschränken.

Bietchiebatchie
2007-07-19, 16:21:54
int foo(IBar x)
{
x.setValue(1);
return x.getValue();
}
Erwartest du hier etwa unterschiedliches Verhalten, abhängig davon ob x eine Boxed-Instanz oder eine "echte" Referenztypinstanz ist? Aus welchem Grund sollte ich denn glauben dass eine Boxed-Instance immutable ist? Weil irgendjemand ohne nachzudenken diesen Quatsch im Internet verbreitet?

Äh es geht nicht darum wie sich das Objekt verhält, wenn du es benutzt, sondern dass sich das Value-Objekt außerhalb des Scopes, in dem es definiert wird, verändert wird. Und das ist zumindest in meinen Augen sehr seltsam.

Xmas
2007-07-19, 16:33:15
Äh es geht nicht darum wie sich das Objekt verhält, wenn du es benutzt, sondern dass sich das Value-Objekt außerhalb des Scopes, in dem es definiert wird, verändert wird. Und das ist zumindest in meinen Augen sehr seltsam.
Wird es ja gar nicht. Die Boxed-Instanz ist ein neues Objekt auf dem Heap und verhält sich wie eine Referenztyp-Instanz.

Bietchiebatchie
2007-07-19, 16:37:42
Ja und genau weil sie sich wie ein Ref-Type verhält wird sie auch verändert, obwohl sie vom (Grund)typ ein Valuetype ist.

Xmas
2007-07-19, 17:07:41
Und ich sehe nicht was daran seltsam sein soll.

Bietchiebatchie
2007-07-19, 17:17:52
Und ich empfinde es halt als seltsam...
Allerdings sehe ich keine Möglichkeit(und auch keine Notwendigkeit) dir dieses komische Gefühl im Magen zu vermitteln, dass das bei mir verursacht ;)