Laden...

Schwächen der C#-Sprache

Erstellt von LastGentleman vor 18 Jahren Letzter Beitrag vor 18 Jahren 12.667 Views
LastGentleman Themenstarter:in
1.274 Beiträge seit 2005
vor 18 Jahren
Schwächen der C#-Sprache

[EDIT]Abgeteilt von Sprachverwässerung [/EDIT]

C# hat meiner Meinung nach ganz andere Schwächen ...

Darf ich fragen welche, wären das?

"Das Problem kennen ist wichtiger, als die Lösung zu finden, denn die genaue Darstellung des Problems führt automatisch zur richtigen Lösung." Albert Einstein

4.207 Beiträge seit 2003
vor 18 Jahren

Klar 😉.

Zum Beispiel ... öfters mal Verletzung der Uniformitätsprinzips:

MyClass myObject = new MyClass();
myObject.FooBar = 23;

Was ist FooBar? Ein öffentliches Feld oder eine Eigenschaft? Und egal ist das nicht, Stichwort Overhead durch Stackschieberein bei Methodenaufrufen. Und wenn man dann einige verschachtelte Elemente hat, macht das durchaus einen Unterschied in der Performance.

Nächstes Beispiel:

MyFooBar aFooBar = new MyFooBar();
SomeClass.SomeMethod(aFooBar);

Ändert sich aFooBar durch den Methodenaufruf? Beziehungsweise, kann es sich ändern? Das hängt davon ab, ob es by Value oder by Reference übergeben wird, was davon abhängt, ob MyFooBar eine Klasse oder eine Struktur ist - nur sehe ich das leider nicht.

Noch ein Beispiel:

string a = "Hallo";
string b = "Hallo";
Console.WriteLine(a == b);

Warum kommt da "true" raus? string ist ein Referenztyp, verhält sich in diesem Fall aber wie ein Wertetyp.

Und so weiter .... 😉

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

502 Beiträge seit 2004
vor 18 Jahren

Original von Der Eisbär
MyClass myObject = new MyClass();
myObject.FooBar = 23;

Was ist FooBar? Ein öffentliches Feld oder eine Eigenschaft? Und egal ist das nicht, Stichwort Overhead durch Stackschieberein bei Methodenaufrufen. Und wenn man dann einige verschachtelte Elemente hat, macht das durchaus einen Unterschied in der Performance.

Ok, Performance ist eigentlich immer ein Kritikpunkt... auch wenn ich es hier für nicht so extrem einflußreich halte.
Ob das nun ein Feld ist oder eine Eigenschaft kannst Du natürlich nicht unterscheiden. Ich denke aber das ist auch gar nicht gewollt, denn Eigenschaften sollen ja per Definition nach aussen ein Verhalten an den Tage legen als wären sie Felder... nur eben mit dem kotrollierten Weg des Zugriff über Getter/Setter.
Ausserdem gibt's dafür Styleguides, die Dir die Unterscheidung durch den Namen des Feldes/der Eigenschaft erlauben - Du musst Dich nur dran halten 😉

Original von Der Eisbär
MyFooBar aFooBar = new MyFooBar();
SomeClass.SomeMethod(aFooBar);

Ändert sich aFooBar durch den Methodenaufruf? Beziehungsweise, kann es sich ändern? Das hängt davon ab, ob es by Value oder by Reference übergeben wird, was davon abhängt, ob MyFooBar eine Klasse oder eine Struktur ist - nur sehe ich das leider nicht.

Zum Thema, ob sich aFooBar ändert oder nicht- da kann ich nur sagen: Traurig aber war... Aber irgendeinen Tod muss man wohl sterben, wenn man im Gegenzug dafür eigentlich durchgängig die gleiche Behandlung von Werte- und Referenztypen erhält (zumindest was die Syntax angeht) 😉

Original von Der Eisbär
string a = "Hallo";
string b = "Hallo";
Console.WriteLine(a == b);

Warum kommt da "true" raus? string ist ein Referenztyp, verhält sich in diesem Fall aber wie ein Wertetyp.

Ganz einfach: Die string-Klasse hat den ==-Operator überladen... Völlig legitim.
Andererseits könnte man es auch ohne diesen Aspekt völlig konsistent erklären: In .net ist erstmal alles ein Objekt, eben auch die Literale wie "Hallo" - sonst ginge ja auch sowas nicht:

int length = "Hallo".Length;

Von der Seite betrachtet, weist Du ja beiden "Referenztypen"-Variablen a und b das selbe Objekt zu und erhälst deswegen auch True.

Wobei man hierbei aber sowieso nicht vergessen sollte, dass string eine "Mischform" aus Referenz- und Wertetyp darstellt... Wer mag kann sich hierzu ja mal die internen string-Verwaltungmechanismen zu Gemüte führen - sehr spassig 😉

Bart Simpson

Praxis ist wenn alles funktioniert und keiner weiss warum.
Theorie ist wenn man alles weiss, aber nichts funktioniert.

Bei uns wird Theorie und Praxis vereint: Nichts funktioniert und keiner weiss warum...

4.207 Beiträge seit 2003
vor 18 Jahren

Original von Mr. Bart Simpson
Ok, Performance ist eigentlich immer ein Kritikpunkt... auch wenn ich es hier für nicht so extrem einflußreich halte.

Wie gesagt, verschachtel das mal, und dann greif darauf mal in einer Schleife zu - das macht definitiv einen Unterschied, ob ich 20.000 Mal auf Felder zugreife, oder ob ich implizit 20.000 Methoden aufrufe (oder eventuell sogar mehr), wovon ich nichts sehe im Code.

Original von Mr. Bart Simpson
Ob das nun ein Feld ist oder eine Eigenschaft kannst Du natürlich nicht unterscheiden. Ich denke aber das ist auch gar nicht gewollt, denn Eigenschaften sollen ja per Definition nach aussen ein Verhalten an den Tage legen als wären sie Felder... nur eben mit dem kotrollierten Weg des Zugriff über Getter/Setter.
Ausserdem gibt's dafür Styleguides, die Dir die Unterscheidung durch den Namen des Feldes/der Eigenschaft erlauben - Du musst Dich nur dran halten 😉

Mir ist klar, dass es Styleguides gibt, das ändert aber nichts daran, dass die Schwäche in der Sprache enthalten ist.

Original von Mr. Bart Simpson
Ganz einfach: Die string-Klasse hat den ==-Operator überladen... Völlig legitim.

Warum das technisch gesehen so ist, ist mir schon klar 😉. Es ging mir mehr um die Motivation dahinter. Warum sollte ich bei einem Referenztypen so tun, als sei es keiner? Es gibt schließlich die Equals-Methode ...

Original von Mr. Bart Simpson
In .net ist erstmal alles ein Objekt,

Nein. Intern arbeitet auch die CLR nur mit Stack und Heap. Ein int ist ein Wertetyp, Punkt. Ob Dir die CLR etwas anderes vorspielt, ist ja etwas anderes 😉.

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo Der Eisbär,

Wie gesagt, verschachtel das mal, und dann greif darauf mal in einer Schleife zu - das macht definitiv einen Unterschied, ob ich 20.000 Mal auf Felder zugreife, oder ob ich implizit 20.000 Methoden aufrufe (oder eventuell sogar mehr), wovon ich nichts sehe im Code.

Also bei 20.000.000 Aufrufen in einer for-Schleife, die auf ein int-Feld bzw. eine int-Property zugreift, bekomme ich Laufzeiten von 31ms zu 46ms. Das scheint mir das Argument doch sehr zu entkräften. Außerdem könnte der Compiler die Properties wegoptimieren. Wäre es dann eine Schwäche der Sprache, dass man nicht wüsste, ob er das tut oder nicht, weil man dadurch die Performance nicht abschätzen kann?

Warum das technisch gesehen so ist, ist mir schon klar 😉. Es ging mir mehr um die Motivation dahinter. Warum sollte ich bei einem Referenztypen so tun, als sei es keiner? Es gibt schließlich die Equals-Methode ...

Schon lustig: In C/C++ wird es als Schwäche angesehen, dass == nicht die Strings vergleicht. 🙂

herbivore

4.207 Beiträge seit 2003
vor 18 Jahren

Original von herbivore
Wäre es dann eine Schwäche der Sprache, dass man nicht wüsste, ob er das tut oder nicht, weil man dadurch die Performance nicht abschätzen kann?

IMHO ja .... C# macht für meinen Geschmack zu vieles implizit.

Original von herbivore
Schon lustig: In C/C++ wird es als Schwäche angesehen, dass == nicht die Strings vergleicht. 🙂

Habe ich auch in Java lange Zeit als störend empfunden, inzwischen bereue ich meine Sicht von damals 😉.

Viele Grüße,

Golo

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

S
8.746 Beiträge seit 2005
vor 18 Jahren

Original von Mr. Bart Simpson

Original von Der Eisbär
MyClass myObject = new MyClass();
myObject.FooBar = 23;
Ob das nun ein Feld ist oder eine Eigenschaft kannst Du natürlich nicht unterscheiden. Ich denke aber das ist auch gar nicht gewollt, denn Eigenschaften sollen ja per Definition nach aussen ein Verhalten an den Tage legen als wären sie Felder... nur eben mit dem kotrollierten Weg des Zugriff über Getter/Setter.

Steck mal ein Property in eine Funktion, und zwar als "ref" oder "out"-Parameter. Geht nicht. Insofern ist die Kritik berechtigt. Properties und Felder sehen gleich aus, verhalten sich aber eben nicht gleich. Aber natürlich ist das .NET geschuldet. Intern sind Properties Funktionen, und die kann man eben nicht wie Felder behandeln.

Operatorüberladungen halte ich hingegen für komplett unnötig (schon == finde ich kritisch, siehe String-Kritik). Bei Generics gilt das in meinen Augen erst recht. Es wird damit eine Semantik suggeriert, die aber i.d.R. keineswegs klar ist. Operatorüberladung ist was für Schreibfaule.

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo zusammen,

Properties und Felder sehen gleich aus, verhalten sich aber eben nicht gleich.

wenn man keine öffentlichen Felder benutzt, was man m.E. einhalten sollte, dann hat man das Problem kaum mehr.

herbivore

4.207 Beiträge seit 2003
vor 18 Jahren

Das stimmt schon, es ändert aber nichts daran, dass C# das Prinzip der Uniformität verletzt.

Ob man das nun so machen sollte oder nicht, ist ja eine andere Frage, als die Frage, warum die Sprache so etwas überhaupt auf eine gewisse Art und Weise macht.

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo Der Eisbär,

wie könnten denn deiner Meinung nach Properties aussehen, die das Problem nicht aufweisen? Oder würdest du ganz auf Properties verzichten wollen?

herbivore

4.207 Beiträge seit 2003
vor 18 Jahren

Eigenschaften sind intern Methoden. Als ebensolche sollten sie auch dargestellt werden. Aufruf also zumindest mit ().

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

2.082 Beiträge seit 2005
vor 18 Jahren

Hallo Der Eisbär,

was genau schwebt dir da im Sinn? instanziierteklasse.GetIntWert()?

Es ist toll jemand zu sein, der nichts von der persönlichen Meinung Anderer hält. - frisch-live.de

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo Der Eisbär,

und wie unterscheidet man dann Methoden und Properties? Immerhin werden Properties xml-serialisiert, aber Methoden nicht. Nicht dass man da gleich wieder die Uniformität verletzt. 🙂

herbivore

502 Beiträge seit 2004
vor 18 Jahren

Original von frisch
instanziierteklasse.GetIntWert()?

...niemand hält Dich davon ab, genau das zu tun. Aber ich weiss nicht, ob das der Weisheit letzter Schluß ist 😉 Ich bin ganz im Gegenteil sehr dafür, die Eigenschaften einer Klasse (im wesentlichen) so nutzen zu können, als wären es Felder oder Variablen - das macht vieles einfach bequem handhabbar... Frei nach dem Motto "Faulheit siegt" 😁

Bart Simpson

Praxis ist wenn alles funktioniert und keiner weiss warum.
Theorie ist wenn man alles weiss, aber nichts funktioniert.

Bei uns wird Theorie und Praxis vereint: Nichts funktioniert und keiner weiss warum...

2.082 Beiträge seit 2005
vor 18 Jahren

Ich bin zwar noch nicht so tief in der Sprache eingestiegen, dennoch denke ich das es Properties dem Programmierer erleichtert, da es schließlich für einen die Get und Set Methoden automatisiert abnimmt und der Programmierer demnach auch ReadOnly variablen Definieren kann.

//Edit: Eben drum, ich bin mit den Properties auch glücklich ^^

Es ist toll jemand zu sein, der nichts von der persönlichen Meinung Anderer hält. - frisch-live.de

4.207 Beiträge seit 2003
vor 18 Jahren

Hallo,

ich sag ja auch nix dagegen, dass Eigenschaften dem Entwickler vieles erleichtern, ich finde es aber dennoch kein gutes Sprachdesign, dass es zwei verschiedene Konzepte gibt, die gleich aussehen und nicht unterscheidbar sind.

Viele Grüße,

Golo

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

4.207 Beiträge seit 2003
vor 18 Jahren

Original von frisch
was genau schwebt dir da im Sinn? instanziierteklasse.GetIntWert()?

Ja ... genau so macht es ja beispielsweise Java, was ich in dieser Hinsicht sauberer finde als C#.

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo Der Eisbär,

nein, ich meine, das ist nicht in jeder Hinsicht sauberer. Allerdings müsste ich für die genaue und saubere 🙂 Begründung erstmal ein Buch konsultieren, das ich gerade nicht zur Hand habe.

herbivore

4.207 Beiträge seit 2003
vor 18 Jahren

Das würde mich mal interessieren, also her damit 😉

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

J
42 Beiträge seit 2006
vor 18 Jahren

String ist übrigens ein Wertetyp

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo Jabberwocky,

das stimmt nicht! String ist ein Referenztyp, da String eine Klasse und kein Struct ist.

herbivore

J
42 Beiträge seit 2006
vor 18 Jahren

Hast recht, er ist als Klasse definiert.

Hab mich davon täuschen lassen, dass er sich in so ziemlich allen mir bekannten Belangen wie ein Wertetyp verhält.
So liefert er immer eine neue Instanz wenn er verändert" wird.
Woraus folgt, dass er sich auch bei Parameterübergabe anfühlt wie ein Wertetyp.

Die Lehre die man daraus ziehen kann:
Struct ist ne schwächere Definition als class, denn eine class kann das äußere Verhalten eines structs annehmen, aber andersrum ist es nicht möglich.

Ich empfinde das aber trotzdem nicht als eine "Schwäche in C#", das etwas nicht das ist, wofür man es hält.
IntelliSense ersetzt eben nicht Doku lesen, das ist eigentlich der einzige Schluss den man aus den aufgezählten "Schwächen" ziehen kann (wie das mit den Properties z.B. auch)

M
456 Beiträge seit 2004
vor 18 Jahren

Strings werden in C#/.NET auch besonders behandelt (mal unabhängig davon ob Wert- oder Referenztyp).
.NET führt intern eine Art globalen Pool für Strings. Hast du mehrere Strings mit dem gleichen Inhalt, dann werden sie nicht mehrfach gespeichert, sondern es zeigt ein interner Verweis auf die gemeinsame Zeichenkette. Veränderst du dein String, dann wird geprüft ob sich dieses ebenfalls noch im Pool befindet. Wenn nicht, wird erst eine echte Kopie mit neuem Verweis im Pool erzeugt.

I am Jack's smirking revenge.
I am Jack's raging bile duct.
I am Jack's cold sweat.
I am Jack's complete lack of surprise.
I am Jack's broken heart.
I am Jack's wasted life.

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo maxE,

soweit ich weiß, wird nur für Litereale zur Übersetzungszeit geguckt, ob ein Literal mehrfach vorkommt und es dann nur einmal gespeichert.

Veränderst du dein String, dann wird geprüft ob sich dieses ebenfalls noch im Pool befindet. Wenn nicht, wird erst eine echte Kopie mit neuem Verweis im Pool erzeugt.

Strings veränden kann man ja in C# eh nicht. Aber für die zurückgelieferten Strings einer "veränderden" Operation (wie ToUpper) kann ich mir das mit dem Pool nicht recht vorstellen. Woher hast du diese Information?

herbivore

C
1.215 Beiträge seit 2004
vor 18 Jahren

Irgendwo hatte ich mal eine String-Class für .NET gesehen, die im Grunde eine String-Collection war. Mit den zugehörigen Methoden und Operatorenüberladung erschien sie nach aussen wie ein gewöhnlicher string, mit dem Vorteil, dass die einzelnen Operationen eben nicht stets einen neuen string erzeugten - natürlich mit klaren Performance-Einbussen.

Zu der Diskussion mit Feldern und Properties...
Eine Klasse sollte am besten gar keine öffendlichen Felder enthalten, es sei denn, sie sind schreibgeschützt.
Ich habe noch keine Klasse gesehen, die öffendliche Felder als Instanzmembers verwendet - weder im Framework noch von Dritten.

Öffendliche Felder als Instanzmembers sind in meinen Augen ein klarer Designfehler und gefähreden die interne Konsistenz, wenn sie zu dem auch noch beschreibbar sind.
Öffendliche Felder sollten am besten nur als statische schreibgeschützte Members eingesetzt werden.

In Java sieht das z. B ebenso aus - ich habe dort noch nie gesehen, dass eine Klasse öffendlichen Zugriff auf Felder bietet.

Grüsse

4.207 Beiträge seit 2003
vor 18 Jahren

Original von Cord Worthmann
Zu der Diskussion mit Feldern und Properties...
Eine Klasse sollte am besten gar keine öffendlichen Felder enthalten, es sei denn, sie sind schreibgeschützt.
Ich habe noch keine Klasse gesehen, die öffendliche Felder als Instanzmembers verwendet - weder im Framework noch von Dritten.

Sorry, wenn ich da jetzt nochmal drauf herumreite - dass es schlechtes Design ist, so etwas zu machen, bestreite ich nicht. Das hat aber nichts damit zu tun, ob es ein gutes Sprachfeature ist oder nicht.

goto ist ein schlechtes Sprachmerkmal, trotzdem kann ich (auch mit goto) gut designte Programme schreiben - das sind zwei paar Schuhe.

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

M
456 Beiträge seit 2004
vor 18 Jahren

@herbivore

Ja, du hast recht. Ein String kann man nicht direkt verändern, sondern sich nur eine modifizierte Kopie zurückgeben lassen. Mit verändern hab ich eigentlich auch mehr das Neuzuweisen von Strings gemeint (Im Sinne von: s = s + "xyz").
Hier was zum String-Pool den .NET verwaltet: http://www.yoda.arachsys.com/csharp/strings.html (Abschnitt Interning)
Mehrere Strings mit gleichem Inhalt werden zur Compilezeit nur einmal gespeichert und als "intern" markiert. Mit String.Intern()/IsInterned() kann man überprüfen ob ein zur Laufzeit erzeugtes String schon in diesem String-Pool vermerkt ist.

I am Jack's smirking revenge.
I am Jack's raging bile duct.
I am Jack's cold sweat.
I am Jack's complete lack of surprise.
I am Jack's broken heart.
I am Jack's wasted life.

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo maxE,

puh, mein Weltbild ist gerettet:

Was die Übersetzungszeit anbelangt, haben wir ja eh das gleiche gesagt: Mehrere Strings mit gleichem Inhalt werden nur einmal abgelegt.

Was die Laufzeit anbelangt ich habe ein kleines Testprogramm geschrieben: Wenn das Ergebnis einer Operation ein String ist, der schon im Pool vorhanden ist, wir trotzdem ein neuer String geliefert. Man könnte sich dann zwar mit IsInterned den zugehörigen String aus dem Pool geben lassen, aber erstmal bekommt man einen neuen.

Hallo Der Eisbär,

herbivore schrieb:
nein, ich meine, das ist nicht in jeder Hinsicht sauberer. Allerdings müsste ich für die genaue und saubere 🙂 Begründung erstmal ein Buch konsultieren, das ich gerade nicht zur Hand habe.

leider habe ich in dem besagten Buch nicht die knackige Formulierung gefunden, die ich dort zu finden glaubte. Deshalb muss ich selber in die Tasten hauen bzw. zum Clipboard greifen:

herbivore schrieb in
>
:
Für mich sind Zustand, Verhalten und Identität so was wie die "Dreieinigkeit" der Objektorientierung. Ein Objekt setzt sich für mich also aus diesen drei Teilen gleichberechtigt zusammen.

Im ersten Ansatz ist der Zustand durch die Felder (Instanzvariablen), das Verhalten durch die Methoden und die Identität durch die Referenz des Objekts bestimmt.

herbivore schrieb in
>
:
Die entscheidende Frage ist, was man als Zustand (state) des Objekts ansieht. Je nachdem welche Sicht man dabei einnimmt, kommt man zu unterschiedlichen Ergebnissen.

Aus der Sicht des Benutzers einer Klasse wie beispielsweise Datum mit den Properties Tag, Monat und Jahr, bestimmt der Wert dieser drei Properties den Zustand des Objekts. Was anderes kann man von außen ja auch nicht sehen. Wir könnten das also den äußeren Zustand nennen. [...]

Aus der Sicht des Implementierers der Klasse Datum sieht die ganze Sache anderes aus. Für ihn ist der Zustand des Objekts gegeben durch die Felder (Exemplarvariablen) des Objekts. Das könnten z.B. die Anzahl der Sekunden seit dem 01.01.1970 sein, also eine ganz andere Repräsentation als die, die der Benutzer der Klasse sieht. (Kleiner Einschub: In meinen Augen sind alle Felder private oder protected, aber nie public. Will man eigentlich, dass ein Feld auch nach außen zur Verfügung steht, dann stellt man stattdessen eine entsprechende public Property zur Verfügung, lässt das Feld selbst aber private oder protected.) Die Felder kann man also nur von innen sehen. Wir könnten das also den inneren Zustand nennen.

Ok, um auf nun auf die Fragestellung in diesem Threads zu kommen: Hier müsste die Argumentation natürlich genau andersherum laufen: Da es eine klare konzeptionelle Trennenung zwischen Zustand, Verhalten und Identität gibt und da es die Notwendigkeit gibt, inneren und äußeren Zustand zu trennen, braucht man eine geeignete Repräsentation des äußeren Zustands. Dafür (Zugriffs-)Methoden zu verwenden, wäre verfehlt, weil dann der äußere Zustand dem Verhalten des Objekts zugeschlagen wird, es aber eine klare Trennung zwischen Zustand und Verhalten geben sollte. Und so kommen die Properties in Spiel. Dass die Syntax von Properties und Feldern beim Zugriff gleich ist, geht ok, weil sie zwei Seiten derselben Medaille sind: äußerer und innerer Zustand. Wenn die Syntax von äußerem Zustand und Verhalten gleich wäre, sich aber von der Syntax des inneren Zustand unterscheiden würde, wäre das weniger schön.

Es sind also letztendlich die allgemeinen Konzepte der OO, die in C# in eine m.E. passendere Syntax gegossen werden als in Java.

herbivore

J
42 Beiträge seit 2006
vor 18 Jahren

Also rein formal definiert bilden alle Felder der Klasse den Zustand, und Properties sind Ausgabefunktionen, die vom Zustand abhängen oder Eingabefunktionen, die den Zustand ändern.

Siehe zum Beispiel Moore-Automat, oder noch besser, Turing-Maschine 😉

Man kann eine Klasse eigentlich parallel zu nem Automaten definieren:
Eine Menge an Zuständen
Zustandsübergangsfunktionen
Ausgabefunktion

Es ist da schon richtig, dass Properties und Funktionen in die gleiche Kategorie gehören.
Ich seh nur irgendwie das Problem das daraus erwächst nicht so richtig.
Nur weil sie syntaktisch wie Felder aussehen ist das eine Schwäche?

Was soll man denn bitte zu Delegates sagen? Mal wie ein Feld mal wie ne Funktion.
Daraus erwächst aber kein Problem, weil es wohldefiniert ist.

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo Jabberwocky,

mir ist schon klar, das man das so sehen kann. Aber ich halte das für eine sehr technische, wenig hilfreiche Sicht. Eine Property wie


public String Vorname
{
   get { return _strVorname; }
   set { _strVorname = value; }
}

ist mindestens mal ein Zwitter. Technisch gesehen sicher eine Methode, aber inhaltlich gesehen ist es mehr ein Feld oder sagen wir Attribut (Attribut im oo Sinne, nicht im .NET Sinne). Da aber für den Benutzer der Klasse die Implementierungsdetails unerheblich sind, wäre es auch egal, wenn im getter oder setter echte Berechnungen stattfinden würden. Inhaltlich bleibt es ein Attribut. Ein Attribut (Zustand) ist aber in der OOP absichtlich von den Methoden (Verhalten) getrennt. Und diese Trennung macht Sinn.

herbivore

C
1.215 Beiträge seit 2004
vor 18 Jahren

Original von Der Eisbär

Original von Cord Worthmann
Zu der Diskussion mit Feldern und Properties...
Eine Klasse sollte am besten gar keine öffendlichen Felder enthalten, es sei denn, sie sind schreibgeschützt.
Ich habe noch keine Klasse gesehen, die öffendliche Felder als Instanzmembers verwendet - weder im Framework noch von Dritten.

Sorry, wenn ich da jetzt nochmal drauf herumreite - dass es schlechtes Design ist, so etwas zu machen, bestreite ich nicht. Das hat aber nichts damit zu tun, ob es ein gutes Sprachfeature ist oder nicht.

goto ist ein schlechtes Sprachmerkmal, trotzdem kann ich (auch mit goto) gut designte Programme schreiben - das sind zwei paar Schuhe.

Okay, da hst Du natürlich Recht.

Zu goto...
Das ist übrigens wirklich so eine Sache.
goto gehört eigendlich in keine Sprache, die vordergründig oo erscheinen möchte. Und wahrscheinlich hätte es besser wegfallen müssen.
Allerdings muss ich zugeben, dass ich goto gerne in switch-Anweisungen verwende - quasi als Ersatz für fallthru in Java, C/C++.

Grüsse

I
1.739 Beiträge seit 2005
vor 18 Jahren

Zu goto,

Bei C# macht es in einem switchblock Sinn.
Das goto erlaubt in diesem Fall das Springen zu einer "Basis" jedoch nicht das verlassen des Blocks(gleicht eine Unzulänglichkeit aus, ohne einen wirklichen Sprachfehler zu hinterlassen, gewöhnungsbedürftig?=ja).

4.207 Beiträge seit 2003
vor 18 Jahren

Hallo Herbivore,

erst einmal danke für Deine ausführliche Antwort, ich kann die Argumentation gut nachvollziehen.

Hm, da stellt sich mir nun die Frage - wenn Eigenschaften technisch gesehen für mich ein Problem sind, weil man eben den Unterschied zwischen Feld und Methode nicht mehr sieht, es aber vom Standpunkt der OOP sauberer ist als mit get- und set-Methoden, wie wäre ein Kompromiss denkbar?

Beziehungsweise, wie müsste ein Objektmodell (oder besser gesagt -paradigma) aussehen, um diese Problematik zu umgehen?

Viele Grüße,

Golo

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

S
8.746 Beiträge seit 2005
vor 18 Jahren

Original von ikaros

Das goto erlaubt in diesem Fall das Springen zu einer "Basis" jedoch nicht das verlassen des Blocks(gleicht eine Unzulänglichkeit aus, ohne einen wirklichen Sprachfehler zu hinterlassen, gewöhnungsbedürftig?=ja).

Wenn man es sich genau anschaut, ist goto in switch eine deutlich bessere Lösung, als der C/C++-Fallthrough. Mit goto können nämlich alle Blöcke beliebig in der Reihenfolge vertauscht werden, was bei Fallthrough nicht der Fall ist. Zudem wird das Fehlen eines Blocks (aus Versehen gelöscht) über goto vom Compiler angemeckert, während beim Fallthrough einfach "woanders hingefallen" wird.

J
42 Beiträge seit 2006
vor 18 Jahren

Original von Der Eisbär
Beziehungsweise, wie müsste ein Objektmodell (oder besser gesagt -paradigma) aussehen, um diese Problematik zu umgehen?

Diese Problematik hat mit nem Objektmodell nichts zu tun sondern nur mit nem Syntax. Der Syntax ist eben "property = value;", aber eben nichts anderes als set_property( value );". Das ist eben nur ein Syntax wie du diese Funktion aufrufst. Siehe zum Beispiel die decompilierte Fassung, wo genau diese Funktionen dann drin stehen.
So wie du mit nem Operator eine Funktion aufrufst, die aber nicht nach nem Funktionsaufruf aussieht.

Befassen sich Objektmodelle mit Syntaxproblemen?
Properties sind nichts besonderes, sie sind nur ein vereinfachter Syntax für ganz bestimmte Funktionen, nämlich getter und setter. Bzw. adder und remover bei events 😉

S
8.746 Beiträge seit 2005
vor 18 Jahren

Ich denke auch, es ist ein Syntax-Problem:

Methode: obj.f()
Feld: obj.f
Property: obj.f$ oder so

Auf der anderen Seite ist ja die syntatische Ähnlichkeit zwischen Property und Feld gewollt... es ist eben nicht nur ein Vorteil ein Zwitter zu sein. 😉

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo zusammen,

ich denke es ist alles andere als ein Syntax-Problem. Ich halte es für ein technisches Problem. Wenn sich Properties bei out Parametern genauso verhalten würden, wie bei Feldern, wäre das Problem m.E. schon gelöst (und das wäre durchaus technisch möglich).

Denn den Performance-Unterschied, würde ich - wie oben angedeutet - nicht als schwerwiegendes Problem sehen bzw. eigentlich gar nicht gelten lassen. Ich kann auch einer Methode nicht ansehen, welche Kosten der Aufruf verursacht. Ein List.Remove hat den Aufwand O(n), aber das ist nicht von vornherein klar, sondern erst durch einen Blick in die Doku. Da man die Implementierung von Klassen (normalerweise) nicht kennt (und nicht kennen muss und nicht kennen soll), kann man auch keine Aussagen über den Aufwand einer Operation machen. Insofern halte ich es auch nicht für problematisch, wenn man die Kosten des Zugriffs auf ein Attribut (also Feld oder Property) auch nur der Doku entnehmen kann.

Wenn es weitere Unterschiede zwischen Feld und Property gibt, immer her damit. Ich denke, alle lassen sich technisch lösen.

Hm, da stellt sich mir nun die Frage - wenn Eigenschaften technisch gesehen für mich ein Problem sind, weil man eben den Unterschied zwischen Feld und Methode nicht mehr sieht, es aber vom Standpunkt der OOP sauberer ist als mit get- und set-Methoden, wie wäre ein Kompromiss denkbar?

Der Kompromiss müsste sein, Felder und Properties in ihren technischen Eigenschaften zu vereinheitlichen. So könnte der Compiler z.B. dafür sorgen, dass Properties auch für out Parameter verwendet werden können.

Beziehungsweise, wie müsste ein Objektmodell (oder besser gesagt -paradigma) aussehen, um diese Problematik zu umgehen?

Ich glaube, das Objektmodell/-paradigma ist schon ok, es hapert an der technischen Umsetzung.

herbivore

J
42 Beiträge seit 2006
vor 18 Jahren

Original von herbivore
Hallo zusammen,

ich denke es ist alles andere als ein Syntax-Problem. Ich halte es für ein technisches Problem. Wenn sich Properties bei out Parametern genauso verhalten würden, wie bei Feldern, wäre das Problem m.E. schon gelöst (und das wäre durchaus technisch möglich).

Das Problem ist gelöst wenn man Properties als das betrachtet was sie sind:
Funktionen mit einem vereinfachten Aufrufsyntax

Dann passt plötzlich alles.

6.862 Beiträge seit 2003
vor 18 Jahren

Original von Jabberwocky
Das Problem ist gelöst wenn man Properties als das betrachtet was sie sind:
Funktionen mit einem vereinfachten Aufrufsyntax

Genau das sind sie eben nicht 🙂 Kannst du Funktionen serialisieren? Properties werden fast immer evaluiert wenn drau zugegriffen wird, seis halt beim serialisieren oder auch im Debugger.

Genauso gibts nen Error bei diesem Code:


    class Program {
        static void Main(string[] args) {
            TestClass tc = new TestClass();
            tc.TestProp.x = 5;  // hier der Fehler!
        }
    }

    class TestClass
    {
        Test t;

        public Test TestProp {
            get { return t; }
            set{ t = value; }
        }
    }

    struct Test {
        public int x;
        public int y;
    }

Warum? Weil das nen Property ist, und kein Feld, genau das sagt auch die Fehlermeldung. Also wie schon öfter betont, das ist so nen zwischending und ich sehs einfach als Sprachfeature an!

Ich bin eh der Meinung, der Programmierer muss wissen was er tut, er ist selbst verantwortlich wenn er öffentliche Felder, Properties, Methoden oder sonstwas einer Klasse benutzt und wenn er da Mist baut, ist er selber schuld, und nicht das Sprachdesign weils aufn ersten Blick evtl. mehrdeutig zu sein scheint.

Mag sein dass einige Punkte in C# nicht optimal sind, dafür würde man mit einer hypothetischen Sprache die alle Schwächen versucht auszubügeln, auf eins verzichten: Produktivität!

Weil das muss man C# in Zusammenarbeit mit der .Net Klassenbibliothek lassen. Es ist sehr einfach, produktiv zu programmieren und schnell an Ergebnisse zu kommen.

Baka wa shinanakya naoranai.

Mein XING Profil.

I
1.739 Beiträge seit 2005
vor 18 Jahren

@svenson
absolut richtig, die Lösung ist mit goto am besten. Aber ich wünschte mir anderes Keyword...