AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Boxing und Unboxing in C#

Ein Thema von -187- · begonnen am 25. Aug 2011 · letzter Beitrag vom 26. Aug 2011
Antwort Antwort
Seite 2 von 3     12 3      
-187-

Registriert seit: 24. Sep 2005
483 Beiträge
 
Delphi 2010 Architect
 
#11

AW: Heap und Stack - Unterschiede

  Alt 25. Aug 2011, 18:56
Achso da wird quasi im Hintergrund "geboxt" ? Hmm .. seltsam das Ganze... Aber Anhand deiner Erklärung habe ich folgenden Code aufgestellt. Der Vorteil ist deutlich sichtbar:

Code:
        private void Form1_Load(object sender, EventArgs e)
        {
            int i = 50;
            string s = "50";
            object o = i;
            //object o = s;
            MessageBox.Show(testFunction(o));
        }

        private string testFunction(object o)
        {
            return Convert.ToString(o);
        }
Ich kann über's "Boxing" eine Funktion mit jedem x beliebigen Datentyp aufrufen. Ok, wann und ob ich es brauche wird sich zeigen ...
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#12

AW: Heap und Stack - Unterschiede

  Alt 25. Aug 2011, 19:01
Delphi-Quellcode:
int i = 0;
string s = i.ToString();
Ich denke hier wird implizit das Boxing angewandt.
Es geht auch kürzer:
Code:
(5).ToString()
Da der Typ Int32 zum Glück die .toString() Methode überschreibt, wird hier nicht geboxt. Also schlechtes Beispiel ^^

Aber man deklariere sich einen beliebigen struct und siehe da, man kann toString() aufrufen obwohl das gar nicht deklariert wurde


Zum Beispiel in Java kann man keine generische ArrayList<double> deklarieren, weil die Klasse einen Referenztype haben möchte. Dafür gibt es dann die Wrapperklasse Double (großegeschrieben) ... sowas wollte man sich vll. ersparen.
  Mit Zitat antworten Zitat
SebE

Registriert seit: 31. Jul 2004
Ort: Chemnitz
316 Beiträge
 
Delphi 7 Personal
 
#13

AW: Heap und Stack - Unterschiede

  Alt 25. Aug 2011, 19:04
Eine List<int> und eine List<double> benutzen also die gleiche List<T> wie List<String> oder List<StringBuilder>
Das hab ich nicht verstanden ?
Wie in deinem kleinen ShowMessage-Beispiel:
Code:
public class List<T> where T: object {
  private T[] values;

  public void Add(T value) { ... }
  ...
  }
Code:
public List<string> myStringList;
public List<int> myIntList;
...
Sebastian
  Mit Zitat antworten Zitat
SebE

Registriert seit: 31. Jul 2004
Ort: Chemnitz
316 Beiträge
 
Delphi 7 Personal
 
#14

AW: Heap und Stack - Unterschiede

  Alt 25. Aug 2011, 21:29
Da der Typ Int32 zum Glück die .toString() Methode überschreibt, wird hier nicht geboxt. Also schlechtes Beispiel ^^

Aber man deklariere sich einen beliebigen struct und siehe da, man kann toString() aufrufen obwohl das gar nicht deklariert wurde
Ja, da hast du recht. Auch Int, Bool, ... sind - wie alle Structs - von object abgeleitet (und besitzen u.a. ToString()).

Folgende Ableitungshierachie finde ich irgendwie komisch.
object <-- valueType <-- struct <-- int, wobei object eine Klasse und struct (wie der Name schon sagt) keine ist.
Alles nach valueType (structs, int, ...) liegt auf dem Stack, alle Verweistypen auf dem Heap, wo liegt object?
Sebastian
  Mit Zitat antworten Zitat
Benutzerbild von implementation
implementation

Registriert seit: 5. Mai 2008
940 Beiträge
 
FreePascal / Lazarus
 
#15

AW: Heap und Stack - Unterschiede

  Alt 25. Aug 2011, 21:57
Ich denke hier wird implizit das Boxing angewandt.
Es geht auch kürzer:
Code:
(5).ToString()
Es geht auch noch kürzer:
Code:
5.ToString()
// ... oder ...
"Hello!".ToUpper()


Und SebE: Ein object ist ein Verweistyp -> Heap.
Die Value-Typen sind nicht wirklich von object abgeleitet, dort kommt nur wieder das Boxing ins Spiel.
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#16

AW: Heap und Stack - Unterschiede

  Alt 25. Aug 2011, 22:12
Ja, da hast du recht. Auch Int, Bool, ... sind - wie alle Structs - von object abgeleitet (und besitzen u.a. ToString()).

Folgende Ableitungshierachie finde ich irgendwie komisch.
object <-- valueType <-- struct <-- int, wobei object eine Klasse und struct (wie der Name schon sagt) keine ist.
Alles nach valueType (structs, int, ...) liegt auf dem Stack, alle Verweistypen auf dem Heap, wo liegt object?
object liegt auf dem Heap, wie jeder andere Verweistyp. Falls ein Wert-Typ nach object gecastet wird, wird automatisch ein Objekt erstellt dass den Werttyp beinhaltet.

Das mag am Anfang komisch sein. Aber wenn man darüber Bescheid weiß, ist das halt eine kleine Eigenart die man beachten sollte. In Delphi z.B. ist es nicht ohne weiteres möglich, eine Funktion mit einem Parameter beliebigen Typ zu erstellen. Entweder man überlädt sie x-mal mit TObject, int, long, double, string oder man nimmt einen Variant. Wobei ein Variant mehr Overhead haben dürfte als das boxing.

Btw.: Sooo häufig ist mir das Boxing noch nicht in die Quere gekommen seit ich mit C# einwickle. Eigentlich noch nie. Häufig kann man ja statt structs auch Klassen verwenden, dann hat sich das mit dem Boxing eh erübrigt.

An vielen Stellen wo geboxt wird, wird die nicht geboxte Kopie auch weggeworfen. Zum Beispiel:
Code:
Mein_Eventhandler
{
var abc = new(MyStruct);
abc.Name = NameTxt.Text;
abc.Age = (int)AgeNum.value;
Contactlist.Add(abc);
abc.Haircolor = Color.Green;
}
Jetzt hast du natürlich die Situation dass die Haarfarbe nicht mehr in der Kontaktliste steht. Wenn myStruct eine Klasse wäre, würde es noch übernommen.
Aber der Code sieht ja auch komisch aus. Erst alle Felder befüllen und dann in die Liste rein
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#17

AW: Boxing und Unboxing in C#

  Alt 25. Aug 2011, 22:14
Es ist übrigens sehr wohl möglich, primitive Datentypen als var- oder out-Parameter zu übergeben. AFAIK wird dabei auch nicht im Hintergrund rumgeboxed, sondern lediglich die Zeigernatur (wie auch in Delphi) via Sprachmitteln verborgen. Ebenso ist die Typsicherheit durch den Compiler gewährt. Alles in allem ist das ja eigentlich "nur" konsequentes OOP Durchziehen, so dass - zumindest semantisch - immer alles Objekte sein können.
Ich bin zudem nicht völlig davon überzeugt, dass die Runtime da hinter den Kulissen wirklich in vollem Umfang ein Objekt nach "allen Regeln der Kunst" aufbaut. Ich mutmaße auch dort eine Portion Compiler- bzw. Runtimemagic mehr, damit solche Dinge nicht allzu teuer werden.
Ich war auch zu Beginn von .NET recht skeptisch und hielt das für Humbug, aber man erhält einfach eine Fülle von Freiheiten und Komfort auf diese so einfache Weise, die man wirklich erst merkt, wenn man die 100ste List<float> nicht separat neu ableiten musste . Und der Preis ist doch eher marginal. Ich habs argwöhnisch erwartet, und lieben gelernt.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#18

AW: Heap und Stack - Unterschiede

  Alt 25. Aug 2011, 22:47
Die Value-Typen sind nicht wirklich von object abgeleitet, dort kommt nur wieder das Boxing ins Spiel.
Doch sind sie, allerdings haben sie eine Identitätskrise.
Zum einen sollen sie sich wie Werte auf dem Stack verhalten, also Artefakte, die nur du ihre tatsächlichen Werte bestimmt sind und die dann auch eine Garbage Collection brauchen.
Aber andererseits, erwartet man von ihnen, dass sie zuweisungskompatibel zu Object oder gar Interfaces sind, und dabei sogar PolyMorphie unterstützen sollen (ToString, Equals, GetHashCode).
Gerade Interfaces sind eine kleine pöhse Falle. Man erwartet es als Anfänger nicht, aber dass hier boxt auch:
Code:
interface ITöröö

  void Abc();
}

struct EinStruct

  public void Abc(){}
}
....
ITöröö xyz = new EinStruct();
Das CLR-Team hat hier einen ganz guten Job gemacht. Denn wenn man ValueTypes als solche benutzt, verhalten sie sich auch so.
Mit allen daraus resultierenden Optimierungen oder auch Performance-Fallen.
Aber andererseits brechen sie .Nets "rooted type system" nicht. Also dass alle Typen auf eine Wurzel zurückgehen.
Wenn man es denn wirklich braucht, kann man sie in eine Referenz stecken, die ein Interface oder vom Typ Object ist.
In dem Moment kann man es auch verschmerzen, dass der ValueType verpackt wird. Denn ohne diesen Mechanismus würde man á la Java nicht weiterkommen.
Eine Box ist hierbei vergleichbar mit einer Klasse, die ein Feld vom Typen deines ValueTypes hat und die gleichen Methoden und Properties hat.
Code:
class PseudoBox : ITöröö
{
   private EinStruct DerWert;
   
  public void Abc()
  {
    DerWert.Abc();
  }
}
Solch eine Box ist übrigens vergleichbar mit den Value classes aus Java. Also Integer anstatt int.
Was die CLR aber für uns tut ist, dass all das transparent passiert. Wir sehen die Box nicht. Wenn wir uns xyz per Reflection anschauen, sehen wir alles aus EinStruct, was da auch hingehört.
ValueTypes und Boxing sind also Taschenspielertricks der CLR um performante native Typen wie Int32 oder Double verwenden zu können, die aber im Typsystem keine komische Ausnahme spielen, sondern sich genauso einfügen, wie alle selbstdefinierten Typen.

Was passiert, wenn man kein Boxing in der Runtime hat sieht man "schön" an Delphi oder Java, denn dort sind native Typen etwas komplett anderes als alle anderen selbst definierbaren Typen.
In Java, kann man native Typen nichtmal für Generics nutzen, in Delphi gibt es Record helpers, aber keinerlei Möglichkeit zum Beispiel Integer oder TDateTime mit Helpers zu erweitern. Wobei letzteres nicht unbedingt einen technischen Grund haben muss. Ich denke da war einfach der Anspruch bei Borlemb nicht hoch genug.
Robert Giesecke
I’m a great believer in “Occam’s Razor,” the principle which says:
“If you say something complicated, I’ll slit your throat.”

Geändert von Elvis (25. Aug 2011 um 22:57 Uhr)
  Mit Zitat antworten Zitat
Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#19

AW: Boxing und Unboxing in C#

  Alt 25. Aug 2011, 22:55
Es ist übrigens sehr wohl möglich, primitive Datentypen als var- oder out-Parameter zu übergeben. AFAIK wird dabei auch nicht im Hintergrund rumgeboxed, sondern lediglich die Zeigernatur (wie auch in Delphi) via Sprachmitteln verborgen.
ref parameter sind tatsächlich Zeiger. Aber das macht die CLR nur mit Parametern. (Weshalb man zum Beispiel keine ref-Parameter für Iteratoren nutzen kann. Denn dort landen diese ja als Felder, und Felder dürfen keine Referenzen sein.


Zitat:
Ich bin zudem nicht völlig davon überzeugt, dass die Runtime da hinter den Kulissen wirklich in vollem Umfang ein Objekt nach "allen Regeln der Kunst" aufbaut. Ich mutmaße auch dort eine Portion Compiler- bzw. Runtimemagic mehr, damit solche Dinge nicht allzu teuer werden.
Natürlich ist eine Box keine eigene Klasse, das wäre ja kaum zu verschleiern und dadurch nicht transparent. Außerdem braucht die Box keine eigenen Metadaten oder Implementierungen der Methoden und spart damit auch einen Batzen an Verwaltung.
Aber der Aufwand der Instanzierung einer Box ist gleichzusetzen mit dem einer Klasse, welche dein Struct als Feld hat. Zaubern kann das CLR Team ja auch nicht. Und sie werden richtige Klassen wohl kaum langsamer instanzieren lassen, nur damit Boxes relativ schneller sind.
Robert Giesecke
I’m a great believer in “Occam’s Razor,” the principle which says:
“If you say something complicated, I’ll slit your throat.”
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#20

AW: Boxing und Unboxing in C#

  Alt 26. Aug 2011, 00:04
Hm, leuchtet irgendwie ein Hätte mir da nur ggf. sowas vorstellen können, wie es z.B. bei Copy-on-Write gemacht wird: Semantisch wird es wie ein Objekt ausgesehen lassen, intern aber so lange als nativer Typ verwaltet, bis man tatsächlich nicht mehr anders kann. So Sachen wie eben "12.ToString()" ließen sich ja umschiffen, ohne da wirklich etwas zu instanziren. Wenn man mal davon absieht, dass die Methode ja eh wie schon erwähnt etwas anders implementiert ist.
Danke dir für die Details!
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:34 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz