Laden...

Sinn und Unsinn von out

Erstellt von Moooitic vor 17 Jahren Letzter Beitrag vor 17 Jahren 10.762 Views
M
Moooitic Themenstarter:in
15 Beiträge seit 2007
vor 17 Jahren
Sinn und Unsinn von out

[EDIT]Abgetrennt von [Artikel] C# und Übergabemechanismen: call by value vs. call by reference (ref/out)[/EDIT]

Hi herbivore, (Hi, Borg natürlich auch 😄)

Wie gesagt ich sage nicht das out kein Sinn macht 🙂
Ich finde sogar das (wie Borg das auch sagt) es mit TryParse besser lesbar und schöner als mit einem TryCatch-konstrukt im Code ist oder mit dem Rückgabekonstrukt das Borg vorgeschlagen hat ist.

Der eigentliche Grund wieso wir aber vor diesem Schönheitsproblem stehlen ist static - ein Konzept das vieles einfacher macht und auch übersichtlicher das allerdings der OOP auch nicht gut tut.

Deshalbt funktioniert die Kombination von static und out auch so gut. (im TryParse zB)
Meiner Meinung nach ist static auch der einzige Punkt in einem Program der en out enthalten sollte da sowieso beide Konzepte nicht OO sind kann man sie auch kombinieren um auf einer anderen Ebene zu programmieren als der OO.

Das Problem ist das int eigentlich so aussehen müsste:


class Int32
{
     public bool Parse(string numberAsString)
    {
        // DO CONVERT - THROW EXCEPTION oder ggf return false
        this.value = number; //CONVERTED VAL
        return true;
    }
}

EDIT:
Damit lässt sich dann nämlich auch recht schöner code schreiben.
// je nachdem ob man bool nutzt oder ein void + Exception muss man mit try arbeiten (was dann nichtmehr so schön ist).


string numberAsString = "42";
int container;
if(container.Parse(numberAsString))
{
   //do good stuff
}
else
   //do bad stuff

Daher gilt für mich auch immer OO vor static (und solchen dingen wie out)

Das Objekt Int32 hat also eine Parse Methoode die das Parsing übernimmt und das value überschreibt.
Das Problem damit ist das die Objekte so sehr groß wachsen können.
Daher gibt es eigentlich ja das Convert-objekt.
Ich denke der grund für Parse / TryParse ist das es bequemer ist ein "Punkt" zu schreiben als ein neues Converter Objekt zu erzeugen.

Alles in allem will ich auch nicht streiten wessen Stil wie besser ist - aber ich hoffe doch das Leute die diesen Beitrag finden über die nutzung von out nachdenken.
Offtmals ist es nicht nötig (und auch im Framework nicht sehr oft zu sehen)

(Immer vergess ich was -_-)

B
1.529 Beiträge seit 2006
vor 17 Jahren

Ich stimme dir prinzipiell zu, allerdings ist die Benutzung einer nicht-statischen Parse-Methode nur für Werttypen (struct) sinnvoll. Bei Referenztypen (class) müsste es dann einen entsprechenden Konstruktor geben.

M
Moooitic Themenstarter:in
15 Beiträge seit 2007
vor 17 Jahren

Original von Borg
Ich stimme dir prinzipiell zu, allerdings ist die Benutzung einer nicht-statischen Parse-Methode nur für Werttypen (struct) sinnvoll. Bei Referenztypen (class) müsste es dann einen entsprechenden Konstruktor geben.

Hey 🙂
Ich habe leider nicht in den Regeln gefunden on Artikel als normale Diskussionsplatform gelten (wenn nicht würde ich dich gerne um eine PN antwort bitten 🙂)

Meine frage ist ein kurzes "Warum?"
Ich verstehe das das verhalten von Referenztypen ein anderes ist als bei Werttypen - nur das ist es doch auch für ganz "normale" arbeiten darauf.

Mir muss klar sein das sich die beiden unterscheiden - trotdem sehe ich nicht was du meinst - das verhalten meiner "Parse"-methode wäre das selbe wie bei einer zuweisung auch.

//Nachtrag zum vorpost ... Convert im Framework ist auch statisch. 😕

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo Moooitic,

eine Diskussion, bei der es um den Artikel selbst oder sinnvollen Ergänzungen dazu geht, ist zulässig und sinnvoll. Die aktuelle Diskussion geht mir allerdings zu weit. Deshalb hatte ich auch auf deinen vorigen Beitrag schon nicht geantwortet, obwohl ich durchaus nicht vollkommen deiner Meinung war. Aber ich wollte die Diskussion eben nicht verlängern. Im Zweifel muss ich sie abtrennen, was aber auch blöd ist, weil zu mindest der Anfang hier gut passt. Ich schließe erstmal.

[EDIT]Ok, ich habe mich entschlossen, einen Teil der Diskussion abzutrennen, damit diese hier frei weiter gehen kann ohne den Artikel-Thread zu überlasten.[EDIT]

herbivore

B
1.529 Beiträge seit 2006
vor 17 Jahren
statische Methoden bei Wert-/Referenztypen

Ok, dann poste ich hier noch mal meine PM an Moooitic:

Zur Klärung:
Werttypen können auch uninitialisiert benutzt werden, so dass ich einfach das Parse einer "leeren" Instanz aufrufen kann.
Bei Referenztypen muss ich allerdings zwingend einen Konstruktor aufrufen, bevor ich irgendwelche Instanzmethoden aufrufen kann.

Als Code:

  
struct Werttyp  
{  
   int val;  
   public Referenztyp( int i ) { val = i; }  
   public bool Parse( string str ) { // ... }  
}  
  
class Referenztyp  
{  
   int val;  
   public Referenztyp( int i ) { val = i; }  
   public bool Parse( string str ) { // ... }  
}  
  
// Jetzt kann ich den Werttyp so parsen:  
Werttyp num1; // deklarieren => Instanz ist uninitialisiert  
num1.Parse( myString ); // direkt Wert laden  
  
// Beim Referenztyp muss ich es so machen:  
Referenztyp num2 = new Referenztyp(); // deklarieren und initialisieren => Instanz ist initialisiert  
num2.Parse( myString );  

Der wichtige Unterschied ist also, dass der Referenztyp bereits fertig initialisiert und konstruiert sein muss, bevor ich Instanzmethoden aufrufen kann. Jetzt gibt es aber vielleicht keinen einfachen Konstruktor. Oder er prüft die Parameter. Oder im Konstruktor müssen irgendwelche Ressourcen gebunden werden.
Auf jeden Fall habe ich - falls es mit irgendwelchen Parametern überhaupt gelingt - völlig unnötig die Instanz konstruiert, da sie beim Parse ja wieder ersetzt werden.
Um das zu umgehen, muss man entweder statische Methoden einsetzen, die keine fertige Instanz brauchen, oder Konstruktoren mit verschiedenen Parameterlisten.

Ich ziehe den zweiten Weg vor, allerdings wollte MS wohl keine Konstrukte wie:
int myInt = new int( "1234" );
Außerdem haben wir dort wieder das Problem der Exception bzw. mehrfachen Rückgabewerte.

T
512 Beiträge seit 2006
vor 17 Jahren

Warum ist es denn für OOP natürlich maximal einen Rückgabewert zu haben?

Ein out Parameter ist doch äquivalent zu dem, was man über return zurückgibt.

e.f.q.

Aus Falschem folgt Beliebiges

M
Moooitic Themenstarter:in
15 Beiträge seit 2007
vor 17 Jahren

Nein imo nicht,
ein out verändert die Umgebung ein return gibt zurück.

Nehmen wir an du bist ein Automat (für fahrkarten) und ich schmeiße
10 Euro in dich.
Dann ist deine Rückgabe object[] {karte,rückgeld} (simpeles-return)
anders mit out
Dann ist mein Rückgabewert karte und das rückgeld erscheint magischerweise dort wo dein 10 Euroschein vor dem kartenkauf war.

Der Automat arbeitet also nicht (wie alle objekte der realen welt) auf einem input -> output shema sondern verändert auchnoch seine Umgebung.

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo Moooitic,

doch, es ist das gleiche. Denn im folgenden Code wird i durch f und g im Prinzip auf gleiche Weise geändert. Es wird die "Umgebung" durch beide Aufrufe gleich stark oder gleich wenig beeinflusst. Und da der Aufrufer bestimmt, welche Variablen er für den return-Wert bzw. für out verwendet, kann es auch nicht passieren, dass ohne sein Wissen etwas geändert wird, was er nicht will.


int i;

i = f ();

g (out i);

herbivore

B
1.529 Beiträge seit 2006
vor 17 Jahren

Ich finde es objekt-orientierter, wenn alle Methoden nur auf einem Objekt arbeiten und entsprechend nur ein Objekt zurückgeben.
Prinzipiell macht es ja auch keinen Unterschied, ob ich jetzt verschiedene Variablen bereitstelle, die mir die Methode füllt, oder ob mir die Methode ein Objekt, das alle Rückgabewerte enthält, zurückgibt.
Bei einem out-Wert fällt das auch noch nicht auf. Bei mehreren jedoch ergibt sich ein Verstoß gegen das Gebot der Kapselung, weil zusammengehörige Daten unabhängig gespeichert werden.

Deutlich wird das vielleicht an diesem Beispiel:

public bool ParseIPandPort( string Input, out uint IPAddress, out ushort Port )
// Benutzung:
uint IPAddress; // diese beiden Variablen haben (semantisch) überhaupt nichts
ushort Port; // miteinander zu tun, obwohl sie logisch zusammengehören
if (ParseIPandPort( Input, out IPAddress, out Port ))
{
   // ...
}

Im Gegensatz zu:

public class IPandPort
{
   uint IPAddress;
   ushort Port;
}
public IPandPort ParseIPandPort( string Input )
// Benutzung
IPandPort ipap = ParseIPandPort( Input );
if (ipap != null)
{
   // ...
}

EDIT: Code korrigiert.
EDIT2: Text überarbeitet.

M
Moooitic Themenstarter:in
15 Beiträge seit 2007
vor 17 Jahren

Das war auch nicht gemeint. @ herbivore

Die 10 euro in meinem beispiel sollten ja auch verschwinden (keine macht dem Betrug).

Nehmen wir an dein "i" oder mein rückgeld wird auf minus 1 gesetzt - das problem ist das nun das objekt das i enthält crasht weil i NIE minus sein darf.

Es ist in setRueckgeld() (callback) wohl definiert (im return nicht später dazu) in der out variante nicht - daher verändert das objekt "seine umgebung" und "kommuniziert" nicht über rückgaben oder methoden.
Jetzt kann man sagen ja toll i kann aber auch als rückgabe minus sein - richtig aber das oberobjekt hat dies dann provoziert und ist für die rückgabe verantwortlich nun scheib dies mal im out fall (mit 1-3 ijk) auf und sag mir das ist kein schlechter stil.

Was ich meine ist das OO laut allem was ich je gelesen habe bedeutet das Objekte miteinanter kommunizieren können über wohldefinierte schnittstellen.

Allein die wohldefiniertheit ist hier schon nicht gegeben - welches i j k l m wird denn geändert ?

man sollte im fall mehrerer ergebnisse immer ein kontainer nehmen (das ist im framework auch meist so eingehalten objekte oder structs mit 2-4 gettern und settern)

nettes beispiel @ Borg

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo Moooitic,

ich denke, du hast da irgendwo einen Denkfehler, ich weiß aber nicht genau wo. In meinem Beispiel wird eine lokale Variable geändert. Es wurde nicht das Objekt geändert, dass f und g aufruft. Und nochmal: Der Aufrufer bestimmt, welche Variablen er für return-Wert bzw. für out verwendet. Die Methode f bzw. g kann also nichts ändern, was der Aufrufer nicht will.

Allein die wohldefiniertheit ist hier schon nicht gegeben - welches i j k l m wird denn geändert ?

Und wohldefiniert ist hier natürlich auch alles. Bei return gilt genauso, dass die Methode, die den Wert zurückgibt nicht weiß, welches i, j, k, l oder m geändert wird und es spielt für sie auch keine Rolle. Das ist jedenfalls kein Argument gegen out.

herbivore

M
Moooitic Themenstarter:in
15 Beiträge seit 2007
vor 17 Jahren

Nein das stimmt nicht.
Der "Aufrufer" bestimmt im out fall nicht was geändert wird sondern nur was "möglich" ist geändert zu werden - und das ist auch genau die kritik.

In einem Kontainer stecken NUR informationen - diese werden vom aufrufenden objekt ausgewertet.

Es sind jedoch nur informationen die von einem anderen objekt kommen.

in einem out ist NICHT definiert was geändert wird.

Deutlich wird wie schlecht "definiert" die ganze sache ist zB hier.


public bool foo(out int i, out int j)
{
   i = 42;
   // Error
   j = 42;
   return bool
}

Was ist nun wohl im Aufrufenden objekt wohl wenn ein try drum herum war ?
Was würde mit einem Kontainer passieren ?

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo Moooitic,

ich verstehe deinen Einwand nicht. Der Aufrufer hat die volle Kontrolle. Wenn er vermeiden will, dass trotz einer Exception z.B. ungewollt eine Instanzvariable geändert wird, dann kann er das tun.


class A
{
   int _i;

   public void DoF ()
   {
      _i = f ();   
   }

   public void DoG ()
   {
      int i;
      g (out i);   
      _i = i;
   }
}

Beides ist semantisch gleichwertig.

herbivore

M
Moooitic Themenstarter:in
15 Beiträge seit 2007
vor 17 Jahren

Ja , es geht ja eigentlich auch garnicht um "Sinn und Unsinn" (titel kommt von dir ^^) sondern darum was OO der richtigere Stil wäre.

wenn ich dir jetzt ein goto code schreibe dann könntest du mir auch immer das semantisch equivalente codefragment dazu posten 🙂

Ich glaube es gibt eine menge Java erklärungen zu goto und pointern (also dem ahnlichen verhalten wie beim out begriff) die wie ich versuchen zu erklären das out unnötig und nicht OO ist.

Das du sagst out ist wie return ist so einfach nicht richtig.
Ein return ist die antwort darauf das ich gegen die mauer laufe.
Wenn jetzt aber jemand anders gegen die mauer läuft und mir dann die nase weh tut ist das was anderes (weil variable gesetzt in oberklasse).
Natürlich kannst du jetzt sagen das der andere auch meine "istGeggenWandGelaufen()" methode hätte aufrufen können -was so nicht umbedingt stimmt - und natürlich kannst du sagen das der programmierer dafür verantwortlich ist.
Das stimmt auch es geht ja im stil und nicht um müssen.
Ich habe läute schon code schreiben sehen der ref TextBox1 enthalten hat - vielleicht kommt meine abneigung daher - in einem großen projekt bricht dir sowas 297 mal die beine im gegensatz zu wohldefinierten schnittsellen.

Ich sagte auch im vorbeitrag das ich garnicht steiten will ^^
Im gegenteil Borg hat mir sehr schön erklärt warum static ein sinn hat (obwohl ich es nicht als OO ansehe).
Im sinne von TryParse hat out den Sinn der kürzeren Schreibweise. das problem ist wenn man sowas in einem artikel nennt und dazu nicht auf die gefahren hinweist dann findet man es bei nachwüchslern immerwieder weil es "einfacher ist" das mag so auch korrekt ein wenn ich meinen 200 zeiler hinklatsche.

Ich wollte nur den grundgedanken äusern das out nicht wirklich eine andere als die historische bedeutung hat.

Gruß 🙂

PS: ich finde dein Beispiel zeigt die schönheit der return Variante ^^'

T
512 Beiträge seit 2006
vor 17 Jahren

Original von Moooitic
Nein das stimmt nicht.
Der "Aufrufer" bestimmt im out fall nicht was geändert wird sondern nur was "möglich" ist geändert zu werden - und das ist auch genau die kritik.

Nein das stimmt nicht, ein out Parameter MUSS genauso wie ein return gesetzt werden, bevor die Methode verlassen wird.

Innerhalb einer Methode, die mit out Parametern definiert wurde, besteht absolut kein Unterschied zwischen return und out.

Außerhalb der Methode ist in C# der Unterschied, dass man das Return nicht in einer Variable festhalten MUSS. Wohlgemerkt aber in C#, Iron Python z.B. behandelt die Returns und outs völlig gleich.

Du darfst dich nicht an dem TryParse festhalten, du kritisierst schließlich out im Allgemeinen. Es gibt aber Algorithmen, die haben einfach mehrere Rückgabewerte, z.B. div und mod. Hinter den beiden steht exakt der gleiche Algorithmus, also würde man doppelten Code schreiben, wenn man out verwendet. Das hat schon was von Fanatismus im Namen von OOP gegen eines der Grundideen von OOP zu verstoßen.
Oder man führt ein Objekttyp ein, der Tupel beschreibt. Oder man Verwendet Arrays. Nur was ist der Vorteil? Der Nachteil ist, dass man bei einem Tupel und Array an der Signatur der Funktion erstmal nicht weiß, wieviele Werte zurückgegeben werden, und welche Bedeutung diese haben.

e.f.q.

Aus Falschem folgt Beliebiges

M
Moooitic Themenstarter:in
15 Beiträge seit 2007
vor 17 Jahren

Arg, lol,

Ich rede die ganze zeit über ref -_- (daher auch immer der pointer vergleich - out ist ja etwas anders)
(ich hab die beiden mal wieder verwächselt)

In dem Sinn hast du recht "out" ist an sich nichts weiter als ein return mit blödem syntax.
Es ist zwar hässlich das immer feste Variablen überschieben werden aber - wie mans mag. (ich würde es auch nicht nutzen... aber da alle variablen belegt werden müssen ist alles definiert)

Dann entschuldige ich mich natürlich - gegen wohldefinierte mehrfachrückgabe hab ich nichts. ^^

Eine frage bleibt jedoch noch - was passiert in meinem error fall ? s.o (schon das was ich denke oder - die parameter werden nicht am ende überschrieben.

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo Moooitic,

Ja , es geht ja eigentlich auch garnicht um "Sinn und Unsinn" (titel kommt von dir ^^) sondern darum was OO der richtigere Stil wäre.

da würde ich sagen: kommt darauf an. Wenn eine Methode mehrere unabhängige Objekte liefern soll, dann ist out ok. Wenn die Objekte eigentlich zusammengehören, also eine Einheit bilden, wäre es besser eine neue Klasse dafür zu schaffen und ein Objekt dieser Klasse zurück zu geben, wie es Borg oben beschrieben hat.

Machen wir doch mal was anderes. Es gibt ja Programmiersprachen, bei denen man mehrere Objekte returnen kann, also z.B. als Pseudocode:

(i, j) = f ();

int, int f ()
{
   return 1, 9;
}

Wäre das jetzt schlechter oder weniger objektorientiert als wenn man nur einen Returnwert zurückgeben könnte?

herbivore

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo Moooitic,

was den Exception-Fall angeht, hast du schon Recht. Da würde der out-Parameter geändert, die Variable bei einem Return nicht. Das ist tatsächlich ein Unterschied ... wenn und nur wenn, die aufgerufene Methode so programmiert ist, dass trotz möglicher Exceptions die out-Parameter frühzeitig ändert. Das sollte sie nicht tun. Wir reden ja über Stil. Und da sage ich einfach, wenn die aufgerufene Methode stilvoll geschrieben ist, gibt es keinen Unterschied zwischen return und out.

herbivore

M
Moooitic Themenstarter:in
15 Beiträge seit 2007
vor 17 Jahren

neinnein ,
Ich stimme dir voll zu - es ist OO
Mir würde der gedanke nicht liegen das immer irgentwelche variablen überschrieben werden - ich habe immer dieses input -> output shema im kopf und lasse mir lieber einen kontainer geben.
Aber ich stimme voll zu das beides objektorientiert ist.

In meinem automatenbeispiel würde es zwar immernoch heißen das mein 10 euroschein zu einem 5 er wird - aber zumindest ist durch out der beam vorgang definiert und zwar IMMER auf mein geld.

Ich weiß das mein geld danach anders ist als vorher und muss es erneut zählen oder kann davon ausgehen das es anders ist.

Trotzdem halte ich out in seiner anwendung sehr begrenzt und eigentlich nur für Sinnvoll möglich wenn ich rückgabewerte erwarte von den ich weiß das sie wenn alles glatt geht IMMER zu benutzen sind (keine zusatztests) - alles andere würde dann out seine Funktion nehmen.

Danke danke - sorry wegen meiner falschen denkweise.

// Edit zum post hiervor ja ich denke auch das wenn man die methode schreibt es für out einige Funktionale anwendungen gibt 😁

T
512 Beiträge seit 2006
vor 17 Jahren

Original von Moooitic
Arg, lol,

Ich rede die ganze zeit über ref -_- (daher auch immer der pointer vergleich - out ist ja etwas anders)

Damit hab ich schon fast gerechnet, aber dazu möchte ich auch noch was sagen:

Eine dumme Verwendung von Schlüsselworten ist kein Argument gegen die Schlüsselworte, sondern gegen diese Art von Verwendung.

Pointer selbst sind sehr gut mit OOP vereinbar. Man kann einen Pointer genauso als Klasse verstehen, wie ein Array. C++ unterscheidet ja nichtmal zwischen den beiden, und in C# könnte man jedes ref auch durch ein Array ersetzen. Aber ist das dann OOP, nur weil ich das gleiche ohne ref mache?

Sobald du ein normalen Referenztypen übergibst, musst du doch auch damit rechnen, dass die Funktion dieses Objekt verändern kann. Wo ist der Unterschied zu einem Pointer?

e.f.q.

Aus Falschem folgt Beliebiges

M
Moooitic Themenstarter:in
15 Beiträge seit 2007
vor 17 Jahren

Ich weiß daher auch die Stil-frage.

Die sache ist das es ganz bestimmte Gründe für referenztypen in programmiersprachen gibt - sehr simpel - laufzeit und speicher.

Und so dumm das jetzt klingen mag das ist auch der einzige grund warum es referenzen gibt.
Deshalb hat man schon zu Java-zeiten versucht dem Menschen dieses werkzeug wegzunehmen zumindest solange es nicht nötig ist.
Das problem ist das eine vollständige entfernung von referenzen der sprache garnicht gut tuen würde.

Referenzen aber durch den "ref" begrif wieder zu fördern finde ich falsch und dazu stehe ich und das er gegenn die OOP verstößt dazu stehe ich auch. (dreh einfach alle out zu ref in dem beitrag hier um ^^)

Die Kommunikation von Objekten sollte in der OOP ganz klar definiert sein durch ref ist sie das definitiv nicht.

Referenzen sind ein meta-sprachmittel das über der OOP liegt.

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo Moooitic,

Die sache ist das es ganz bestimmte Gründe für referenztypen in programmiersprachen gibt - sehr simpel - laufzeit und speicher.

Und so dumm das jetzt klingen mag das ist auch der einzige grund warum es referenzen gibt.

nein, kann ich schon wieder nicht zustimmen. Referenzen gibt es, damit bzw. weil Objekte eine Identität haben. Ein Objekt auf seinen Zustand zu reduzieren, was passieren würde, wenn es keine Referenzen geben würde, wäre gerade ganz und gar nicht objektorientiert. Laufzeit und Speicher sind allenfalls - wenn auch wichtige - Nebeneffekte.

Ob ref ein objektorientiertes Konstrukt sind oder nicht, darüber kann man sich streiten. Ich bin der Meinung, dass ref nicht gegen die Objektorientierung verstößt, wenn es richtig eingesetzt wird. Eine Referenz auf eine Referenz kann hierbei ebenso Sinn machen, wie eine Referenz auf einen Werttyp.

herbivore

M
Moooitic Themenstarter:in
15 Beiträge seit 2007
vor 17 Jahren

Uh ?

Naja ich weiß was du meinst -
Wenn ich object a und object b vergleiche sind sie nicht gleich weil ihre Referenzen nicht gleich sind (Identität).
Allerdings sehe ich das als den Nebeneffekt an.
Ich kann mir keine Situation denken die eine Referenz hier nötig macht.
Wenn ich davon ausgehe es gibt vieleviele Überschneidungen von wert-technisch-gleichen Objekten dann muss ich ihnen einafch ein 2tes Merkmal geben mit dem ich sie auseinander halten kann.

(um mal Tierfeindlich zu sein) alle Kühe sehen gleich aus.
Also brenn ich ihnen was auf den Hintern = Eigenschaft hinzugefügt.

Ich kann mir nicht vorstellen das die Identität der Hauptgrund für die bindung an Referenzen ist - das hat ein einfachen pragmatischen Computersinn.

Gruß - sorry wenn ich öfter mal falsch lieg oder ihr das meint - mich interessiert aber was ihr denkt.

edit : man meine rechtscheibung ist grottig ...

175 Beiträge seit 2006
vor 17 Jahren

Die Brandmarkung ist nur der eine Teil deiner Tierfeindlichkeit, viel schlimmer ist, dass du ihnen keine eigene Persönlichkeit anerkennst 🙂 Die Identität darf keinesfalls nur über äussere Attribute definiert sein, das wäre äusserst unstrukturiert und liesse enormen Spielram für Unklarheiten.

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo Moooitic,

die Identität ist gerade etwas ganz anders als eine Eigenschaft des Objekts. Auch wenn man technisch gesehen meist nicht umhin kommt, auch eine Id als Eigenschaft in das Objekt zu packen, hat die Identität des Objekts den gleichen eigenständigen Rang, wie Zustand und Verhalten. Zustand, Verhalten und Identität sind die Dreieinigkeit der Objektorientierung. Siehe auch das, was ich in Schwächen der C#-Sprache an den Eisbären geschrieben habe. Wenn ich es mir Recht überlege, gehe ich in Kopie ohne IClonable ausführlicher auf das Thema Dreieinigkeit ein.

herbivore

M
Moooitic Themenstarter:in
15 Beiträge seit 2007
vor 17 Jahren

Hihi 🙂

Em ja das Problem das dahinter steht ist aber wohl eins das nur mit einer gott und die welt diskusion Gelöst werden kann...

Mir persönlih kann nimand beweisen das b nicht a ist wenn a und b einfach VOLLKOMMEN identisch sind 🙂
Nehmen wir an die kuh denkt wie die andere kuh - sieht aus wie sie und auch sonst ist sie wie die andere - dann ist sie noch nicht anders ?
Wer kann mir sagen das dann nicht 2 mal die gleiche kuh da steht ?

Und die OO ist doch ein relativ Weltnahes konzept - warum sollte die identität dann anders sein ?

Zur laufzeit weiß ich ja wieviele kriterien ich zur unterscheindung keinne - und alles was dann gleich ist ist auch glech.

//EDIT sorry post war mal wieder zu spät - ich lese 🙂

175 Beiträge seit 2006
vor 17 Jahren

Überleg dir doch mal was unter "Gleichheit" bei Kühen zu verstehen ist. Wenn du sagst, Kuh a ist dieselbe wie Kuh b, wieso stehen denn da zwei Kühe und fressen dazu noch unterschiedliches Gras... da kann man doch nicht von Gleichheit sprechen, höchstens von Ähnlichkeit

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo Moooitic,

das zwei Kühe so vollkommen gleich sind, ist schwer vorzustellen. Aber nehmen wir was einfacheres: Teebecher. Wenn du zwei Teebecher hast, die vollkommen gleich und nicht zu unterscheiden sind, so hast du doch trotzdem zwei Teebecher. Sie sind damit nicht identisch, obwohl die vollkommen gleich sind.

herbivore

M
Moooitic Themenstarter:in
15 Beiträge seit 2007
vor 17 Jahren

Also ich hab einiges von den Beiträgen gelesen.
Das Problem ist das Wir ja grad daruber reden ob referenztypen eine daseinsberechtigung haben.

Das problem ist folgendes wenn ich kuh a und kuh b habe und alles an ihnen ist gleich.
Dann ist die Identität das merkmal das mir zur unterscheidung der beiden dient.
Es ist ein hashwert des heap der sozusagen einmalig und fest ist.

Er hat jedoch keinen bezug zum objekt selber - das heist das ich darüber nichts weiter als den von gott ( oder meim pc oder meiner vm) gegebenen Gefängnisstrafcode erhalte.

Ich versuche es andersrum:
Wenn jemand denkt wie ihr, und alles an ihm ist wie auch bei euch dann ist er in dem moment der zeit genau die selbe person wie ihr - er steht an der selben stelle (x = 0 , y = 2) wer kann mir nun sagen das ihr nicht gleich seit.

Imo ist die identität ein gedanke der daher kommt das wir alle seit jahrhunderten an seelen und daran glauben das nimand ich ist. Das mag für uns auch gelten weil niemand von uns an x und y stehen kann wenn da ein anderer steht.
Aber es ist nicht gesagt das es daher nicht geht.

das ist dann doch einfach im objekt zu realisiren so das es keine doppelten gbt - es kann kein x , y gleich sein beim Mensch-object - simpel so halt ich sie ggf auseinander.

Nchmal anders :
Man stelle sich vor das object Mensch a b steht an x , y gleich - alle seine eigenschaften sind gleich ALLES ist gleich und doch sind sie nicht glech da Id(a) != Id(b) ... macht das echt mehr Sinn ?

Wie gesagt ich denke das liegt alles an einem Heap-Computer-Konzept das es ref gibt. ( nochmal Laufzeit und speicher als stichwort.)

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo Moooitic,

kurz gesagt: zwischen Gleichheit und Identität zu unterscheiden macht Sinn.

Es ist natürlich so, dass zwei Dinge die identisch sind immer auch zwangsweise gleich sind. Andersherum gilt das aber gerade nicht automatisch.

Mit Heap hat das Ganze gar nichts zu tun.

herbivore

M
Moooitic Themenstarter:in
15 Beiträge seit 2007
vor 17 Jahren

Danach gilt also 2 Objekte die in allem anders sind ABER Id(a) == Id(b) gilt sind "gleich".
Das ist ein unwirklicheres Konzept als die ID als Attribut zu betrachten imo.
Es gibt dafür auch keine Sinnvolle Anwendung.

Nungut - ich bedanke mich für die Meinungen.
Ich wert mal mit ein paar Bekannten drüber reden.

Nettes Thema - Gruß

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo Moooitic,

Danach gilt also 2 Objekte die in allem anders sind ABER Id(a) == Id(b) gilt sind "gleich".

zwei Objekte die in allem anders sind, können nicht identisch sein.

Wenn zwei Objekte identisch sind, dann gibt es ja in Wahrheit nur ein Objekt und in diesem Objekt ist natürlich alles zu sich selbst gleich.

Es gibt dafür auch keine Sinnvolle Anwendung.

Wie kommst du zu so einer völlig haltlosen Behauptung? Offensichtlich hast du das Konzept noch gar nicht verstanden.

herbivore

M
Moooitic Themenstarter:in
15 Beiträge seit 2007
vor 17 Jahren

Original von herbivore
Wie kommst du zu so einer völlig haltlosen Behauptung? Offensichtlich hast du das Konzept noch gar nicht verstanden.

Wenn dem so wäre - würde ich dich darum bitten mich darüber aufzuklären WANN ich denn nun eine Verwaltete ID brauche.

Das Problem das ich mit diesem Konzept habe ist:
objekte die in scope a und scope b exsistieren
sind auch in scope c veränderbar (durch a und b)

PRO

  • speicher (kein copy)
  • laufzeit (kein copy)

KONTRA

  • Ein Objekt sollte im idealfall nie mehr als ein definirtes scope haben.
    Ergebnisse bzw das Objekt (mit neuen Zuständen) kann/können dann ggf in einem neuen scope exsistieren.

Das ist der Grund wieso dieses Konzept heute benutzt wird - weil das andere ineffizient wäre.
Weil es nicht nötig ist ein object immer von scope zu scope zu verscheben wenn man es auch anders (mit bedacht) realisieren kann.
Nichts desdotrotz ist eine Id nicht nötig und das konzept nur ein weg der HardwareTechnisch am besten ist.

S
1.047 Beiträge seit 2005
vor 17 Jahren

Wenn dem so wäre - würde ich dich darum bitten mich darüber aufzuklären WANN ich denn nun eine Verwaltete ID brauche.

ich würd sagen eine verwaltete id brauchst du dann, wenn du anhand der anderen eigenschaften eines objektes keine eindeutige unterscheidung feststellen kannst

das prinzip verwendest du ja z.b. beim modellieren einer datenbank 😉

B
1.529 Beiträge seit 2006
vor 17 Jahren

@Moooitic: Ich glaube, du hast enorme Schwierigkeiten beim Unterscheiden zwischen das Gleiche und das Selbe.

Ich will mich auch mal an einem Beispielen versuchen.

Nehmen wir einfach mal an, zwei eineiige Zwillinge, die sich vom Aussehen, Ansichten und Absichten nicht unterscheiden, wohnen zusammen.
Sie sind also die Gleichen, nicht aber die Selben, also auch nicht identisch.
Dann gibt es zwei Möglichkeiten, wie sie leben.

  1. Sie besitzen genau einen Kleiderschrank, in dem jedes Kleidungsstück genau einmal vorhanden ist. Das bedeutet beide besitzen die selbe Kleidung. Nur einer kann sie gerade anhaben, der andere muss warten oder etwas anderes tragen. => konkurierende Zugriffe

  2. Sie besitzen jeder genau einen Kleiderschrank. In jedem befinden sich die gleichen Kleidungsstücke, d.h. insgesamt sind alle doppelt vorhanden und jeder hat von jedem Kleidungsstück ein eigenes Exemplar. Dann gibt es keine konkurierenden Zugriffe, beide können jeden Tag das Gleiche tragen.

Probleme gibt es nur am Waschtag. Entweder wäscht jeder seine Sachen selbst, dann benötigt man aber wieder zwei Waschmaschinen und zwei Wäscheleinen, um einen neuen konkurierenden Zugriff zu unterbinden, oder alle Sachen kommen auf einen Haufen und werden zusammen gewaschen.
Wenn es ihnen jetzt aber nicht egal ist, ob sie ihr eigenes Hemd oder das des Zwillings bekommen, müssen sie eine Methode einführen, den Besitzer eines Kleidungsstück zu identifizieren, zum Beispiel durch Beschreiben des Etiketts. Das bedeutet jedoch, dass sie die Gleichheit ihrer Kleidung durch Einführung eines künstlichen Identifikationsmerkmals aufgeben, um eine Identifikation zu ermöglichen.

Die Einführung der ID hat einen großen Vorteil. Um die Sachen nach dem Waschen zu sortieren, muss ich jetzt nicht jedes Kleidungsstück genau betrachten; Größe, Form, Farbe und Muster brauche ich auch nicht mehr wahrzunehmen; ich brauche auch nicht schauen, wer dieses Kleidungsstück bereits in seinem Schrank hat.
Nein, statt dessen schaue ich einfach aufs Etikett. Und da steht dann, welchem Zwilling es gehört. Fertig.

Und jetzt kommt der wichtige Unterschied zwischen einem Objekt im Speicher und einem Datensatz in einer Datenbank.
Es gibt keine Reihenfolge der Datensätze, das bedeutet, es gibt kein eindeutiges Identifizierungsmerkmal für einen Datensatz von Seiten des DBMS. Um also einen Datensatz zu identifizieren müsste ich also alle Eigenschaften überprüfen. Nur dann brauche ich keine Datenbank. Wenn ich beispielsweise vom Auftrags-Datensatz auf den Erteiler kommen will, müsste ich dann im Auftrag sämtliche Eigenschaften speichern, um ihn sicher identifizieren zu können. Dann kann ich mir die zweite Tabelle aber gleich sparen. Um dieses Problem zu durchbrechen, wird jetzt einfach im Datensatz ein zusätzliches Identifikationsmerkmal eingefügt. In relationalen Datenbanken nennt man dieses primary key.

Objekten im Speicher ist jedoch aufgrund der linearen Struktur der Speicheradressierung bereits ein solches Identifikationsmerkmal mitgegeben: die Adresse des Objekts im Speicher, also die Referenz.
Und so wie per Definition die gleichen primary keys den selben Datensatz beschreiben, beschreiben die gleichen Referenzen das selbe Objekt. In beiden Fällen vergleiche ich auf Identität.
Vergleiche ich hingegen die Felder eines Datensatzes oder eines Objektes mit denen eines anderen Datensatzes bzw. Objektes, so vergleiche ich auf Gleichheit.
Selbst wenn die Objekte in allen ihren Eigenschaften gleich sind, so kann ich dennoch keine Aussage darüber treffen, ob sie auch die selben (also identisch) sind.

S
8.746 Beiträge seit 2005
vor 17 Jahren

Um nochmal auf return vs. out zurückzukommen. Tatsächlich bergen call-by-reference-Aufrufe das Risiko von Seiteneffekten. In C# ist das Problem allerdings dadurch gemildert, dass sowohl formale UND aktuelle Parameter explizit ausgezeichnet werden. Unbemerkte Modifikationen sind damit so gut wie ausgeschlossen.

Leider checkt der C#-Compiler nicht, ob ein und diesselbe Variable mehrfach als aktueller Referenzparameter verwendet wird. Da Objekte immer by reference übergeben werden, beschränkt sich das Problem sowieso auf Werteparameter.

In der Praxis ist das m.E. akademisch, weil jeder normale Mensch intuitiv return dem out vorzieht. Für Fälle wie COM ist man gezwungen out/ref einzusetzen.

Meiner Erfahrung nach kommt man vielleicht ein oder zweimal pro Projekt in den Konflikt sich zwischen out/ref oder einer kapselnden Klassen zu entscheiden. Ist also nur eine Nebenbaustelle.