Alles (aus) Gold glänzt, aber nicht alles was glänzt ist Gold.
Alle Nüsse sind rund, aber nicht alles, was rund ist, ist eine Nuss.
…
Jeder kocht Zuhause. Aber deswegen ist nicht jeder ein Koch.
Jeder kann ein Auto-Motor oder -Getriebe zerlegen. Aber deswegen ist nicht jeder ein Auto-Mechaniker.
Jeder kann mit einer Lötpistole (oder einem Lötkolben) in einem Radio oder Fernseher herum löten. Aber deswegen ist nicht jeder ein Elektroniker.
Jeder kann mit einem Taschenrechner umgehen, aber deswegen ist nicht jeder ein Mathematiker.
Jeder kann beim Schachspielen drei Züge vorausdenken, aber deswegen ist nicht jeder ein Profi-Schachspieler.
…
Nur weil man in eine Objekt-orientierte Programmier-Sprache wie C++, Java oder C# Code schreibt, heißt es noch lange nicht, dass das Programm (der Code) Objekt orientiert ist!
Ich habe C# Code in „professioneller“ Umgebung (Industrie) gesehen und gelesen … Es war SPS/PLC Programmier-Stil in .NET/C# !
Ja, ich weiß! Ich hätte es selbst nicht geglaubt, wenn ich den Code nicht persönlich gelesen hätte (eine mind. viermonatige Tortur! Eine pure Verschwendung von teurem Arbeits- und Lebens-Zeit! Dazu noch: Augen- und Hirn-Schmerzen sowie schlaflose Nächte! Das wünsche ich niemandem!).
Ich selbst habe früher Mal, als Autodidakt, Visual Basic programmiert, ohne je von OOP, Klassen, Interfaces, Kapselung, Vererbung, Polymorphismus usw. je gehört/gelesen oder verstanden zu haben. Es hat (damals für mich) „funktioniert“. Dessen Code-Qualität war gleich 0 (null), bzw. eher am Ende der Minus-Bereich, je-nach Code-Qualitäts-Bewertungs-System.
Jede Programmier-Sprache hat seine Geschichte, geschichtliche Entwicklung, Konzepte, Paradigmen sowie „Eigenheiten“ und „Features“.
Es ist von großer Wichtigkeit die Geschichte einer Programmier-Sprache, dessen Sprach-/Programm-Elemente, Paradigmen und Konzepte zu kennen. Erst dadurch kann man sie 1.) begreifen und 2.) wissen Wann, Wo, Wie und Warum ein Programm-Element (Pre-Compiler-Symbol, Konstanten, Enumerations, Properties, Delegates, Events, usw.) oder OOP-Muster zu verwenden sei.
Jemand der C++ beherrscht kann nicht automatisch auch Java oder C# beherrschen.
Jemand der Java beherrscht kann nicht automatisch auch C# beherrschen.
Beweis durch Widerspruch:
Annahme: Wer C++ beherrscht, kann automatisch genauso Java/C# beherrschen.
Vergleiche in alle drei Sprachen werden mit dem Schlüsselwort „if
“ durchgeführt.
Gegeben: if ( person != null && person.Name == "Bob" )
und die Variable person
ist null
.
In C++ (bis mind. C99 Standard) wird ein Fehler ausgelöst (Null Reference), weil person.Name == ...
ausgeführt wird, und die Variable person
ist/referenziert ja null
! Man kann nicht auf Etwas das NULL ist, auf dessen Eigenschaft/Variable/Methode (in diesem Fall „Name“) zugegriffen werden.
In Java und C# hingegen geht es gut, weil beide Sprachen den sogenannte „Kurzschluss-Ausschluss-Verfahren“ beim Vergleichen anwenden (was in C++ je nach Compiler und Standard nicht gibt/gab). Das heißt, nachdem „person != null
“ Falsch (false
) ist, und der nächste Vergleich Konjunktiv („&&“) gebunden ist, wird der Rest („person.Name == ...
„) nicht mehr ausgewertet,
da es gilt: false && True_Or_False ==> false
oder binär (0 && (0 || 1) ==> 0
). („==>“ steht hier für „daraus folgt“).
Daher der Name: Kurzschluss-Ausschluss-Verfahren.
Quod erat demonstrandum! (1)
Nun unterscheiden sich auch die Semantik (Bedeutung) und somit das Verhalten zwischen Java und C# auch noch:
Gegeben: person
ist nicht null
UND der Inhalt von person.Name
ist „Bob
„.
In Java: person.Name == "Bob"
erzeugt einen neuen anonymen immutable String Object(eine Konstante) von Typ String
mit dem Inhalt „Bob
“ und vergleicht den Referenzen von person.Name
mit der Referenz von anonymen immutable String Object. Das Resultat ist: false
, da jedes Object auf eine andere Adresse zeigt, und somit es sich um zwei unterschiedliche Referenzen handelt.
In C# werden hingegen die Inhalte von beiden immutable String Objekten (person.Name
und anonymen String
Objekt, = Konstante) durch den Operator „==“ verglichen. Das Resultat ist: true
, da der Wert von „person.Name
“ inhaltlich dem anonymen immutable String Objekt (Konstante) „Bob
“ gleicht.
Kurz: Strings in Java und C# sind immutable Objects (siehe und vergleiche ECMA-334, Abschnitt 8.2.1 „Predefined types“ mit Java-String von Oracle!)
In Java müsste der Code so umgeschrieben werden damit es funktioniert: if (person != null && person.Name.equals("Bob"))
…
Quod erat demonstrandum! (2)
Dazu kommt noch…
Das Kennen von Schlüsselwörter (if, else, new, while
, …) sowie die Grammatik (Syntax) einer Programmiersprache reicht nicht aus um es zu „können“. Man kann dadurch den Code höchstens lesen.
Um eine Programmiersprache zu beherrschen („können“), sind daher weitere Kenntnisse unbedingt erforderlich:
- Paradigmen und Konzepte (Heap vs. Stack, Class vs. Struct, Copy-by-Value, Copy-by-Reference, Immutable Types, OOP Design Patterns, Garbage-Collector/-Collection, Exception-Handling, Generizität, statischer vs. dynamischer Datentyp einer Variable,…)
- Compiler (Was, Wie und Wo wird optimiert? Was wird während Compilierung und was während Runtime (Laufzeit) übersetzt, geprüft, ausgeführt?
Z. B. findet in Java (ab Vers. 1.5 = Java 5) die Typ-Prüfung bei generische Typen erst zur Laufzeit (Runtime), weshalb der Compiler (da Java Type-Safety garantieren möchte) während Compilierung „Warning“ ausgibt.
Bei C# jedoch findet die Typ-Prüfung bei generische Typen während Compilierung statt, und sollte Type-Safety nicht gegeben sein, gibt der C#-Compiler „Error“ aus. Siehe und Vergleiche auch Just-In-Time sowie Ahead-Of-Time Compiler!
Zusätzlich: C# ermöglicht direkten Zugriff und Manipulation auf Speicher und dessen Inhalt (nur wenn der Code-Block mit „unsafe“ Schlüsselwort, sowie die Assembly als „Unsafe“ markiert wird), was in C++ normal/business as usual ist und Java gar nicht anbietet! - Frameworks
- Events bzw. Nachrichten-Schleife
- Parallelität
- …