C-Sharp

Aus besserwiki.de
C#
C Sharp wordmark.svg
ParadigmaMulti-Paradigma: strukturiert, imperativ, objektorientiert, ereignisorientiert, aufgabenorientiert, funktional, generisch, reflektierend, nebenläufig
FamilieC
Entworfen vonAnders Hejlsberg (Microsoft)
EntwicklerMads Torgersen (Microsoft)
Erstmals erschienen2000; vor 23 Jahren
Disziplin der TypisierungStatisch, dynamisch, stark, sicher, Nominativ, teilweise hergeleitet
PlattformGemeinsame Sprachinfrastruktur
Lizenz
  • Roslyn-Compiler: MIT/X11
  • .NET Core CLR: MIT/X11
  • Mono-Compiler: zweifach GPLv3 und MIT/X11
  • DotGNU: zweifache GPL und LGPL
Dateinamen-Erweiterungen.cs, .csx
Websitedocs.microsoft.com/de-us/dotnet/csharp/
Wichtigste Implementierungen
Visual C#, .NET, .NET Framework (aufgegeben), Mono, DotGNU (aufgegeben), Universal Windows Platform
Dialekte
Cω, Polyphonisches C#, Erweitertes C#
Beeinflusst von
C++, Cω, Eiffel, F#, Haskell, Icon, J#, J++, Java, ML, Modula-3, Object Pascal, VB
Beeinflusst
Chapel, Clojure, Crystal, D, J#, Dart, F#, Hack, Java, Kotlin, Nemerle, Oxygene, Rust, Swift, Vala, TypeScript
  • C Sharp Programmierung bei Wikibooks

C# (/si ʃɑːrp/ siehe sharp) ist eine universelle, mehrparadigmatische Programmiersprache. C# umfasst statische Typisierung, starke Typisierung, lexikalische Skalierung, imperative, deklarative, funktionale, generische, objektorientierte (klassenbasierte) und komponentenorientierte Programmierdisziplinen.

Die Programmiersprache C# wurde im Jahr 2000 von Anders Hejlsberg von Microsoft entwickelt und später als internationaler Standard von der Ecma (ECMA-334) im Jahr 2002 und der ISO/IEC (ISO/IEC 23270) im Jahr 2003 anerkannt. Microsoft führte C# zusammen mit .NET Framework und Visual Studio ein, die beide Closed-Source waren. Zu dieser Zeit hatte Microsoft keine Open-Source-Produkte. Vier Jahre später, im Jahr 2004, wurde ein freies und quelloffenes Projekt namens Mono gestartet, das einen plattformübergreifenden Compiler und eine Laufzeitumgebung für die Programmiersprache C# bereitstellte. Ein Jahrzehnt später veröffentlichte Microsoft Visual Studio Code (Code-Editor), Roslyn (Compiler) und die einheitliche .NET-Plattform (Software-Framework), die alle C# unterstützen und kostenlos, quelloffen und plattformübergreifend sind. Mono ist ebenfalls zu Microsoft gestoßen, wurde aber nicht in .NET eingegliedert.

Die neueste stabile Version der Sprache ist C# 10.0 (Stand Juli 2022), die 2021 in .NET 6.0 veröffentlicht wurde.

C# (englisch c sharp [siːˈʃɑːp]) ist eine typsichere objektorientierte Allzweck-Programmiersprache. Architekt der Sprache war Anders Hejlsberg im Auftrag von Microsoft, zurzeit ist Mads Torgersen der Chef-Entwickler. Die Sprache ist an sich plattformunabhängig, wurde aber im Rahmen der .NET-Strategie entwickelt, ist auf diese optimiert und meist in deren Kontext zu finden.

Historisch wurde in C# fast exklusiv für Windows entwickelt. Durch Xamarin ist es inzwischen aber auch möglich, für macOS, iOS und Android zu entwickeln. Zudem gibt es mit .NET Core auch offizielle Unterstützung für GNU/Linux und macOS.

Bis Version 2 war die Sprache bei der ECMA und der ISO als Standard registriert. In der Folge erschienen regelmäßig umfangreiche Erweiterungen der Sprache durch Microsoft. Durch die Entwicklung des Referenz-Compilers als Open Source (seit 2014) sind auch Community-Beiträge möglich.

Entwurfsziele

Der Ecma-Standard listet diese Designziele für C# auf:

  • Die Sprache soll eine einfache, moderne, allgemeine, objektorientierte Programmiersprache sein.
  • Die Sprache und ihre Implementierungen sollten Software-Engineering-Prinzipien wie starke Typüberprüfung, Array Bounds Checking, Erkennung von Versuchen, nicht initialisierte Variablen zu verwenden, und automatische Garbage Collection unterstützen. Die Robustheit der Software, die Dauerhaftigkeit und die Produktivität der Programmierer sind wichtig.
  • Die Sprache ist für die Entwicklung von Softwarekomponenten gedacht, die sich für den Einsatz in verteilten Umgebungen eignen.
  • Die Portabilität ist sehr wichtig für den Quellcode und die Programmierer, insbesondere für diejenigen, die bereits mit C und C++ vertraut sind.
  • Die Unterstützung der Internationalisierung ist sehr wichtig.
  • C# ist für das Schreiben von Anwendungen sowohl für gehostete als auch für eingebettete Systeme geeignet, von sehr großen Systemen, die hochentwickelte Betriebssysteme verwenden, bis hin zu sehr kleinen Systemen mit speziellen Funktionen.
  • Obwohl C#-Anwendungen im Hinblick auf den Speicher- und Rechenleistungsbedarf sparsam sein sollen, ist die Sprache nicht dazu gedacht, in Bezug auf Leistung und Größe direkt mit C oder Assembler zu konkurrieren.

Geschichte

Während der Entwicklung des .NET Framework wurden die Klassenbibliotheken ursprünglich mit einem verwalteten Code-Compiler-System namens "Simple Managed C" (SMC) geschrieben. Im Januar 1999 bildete Anders Hejlsberg ein Team, um eine neue Sprache zu entwickeln, die damals Cool genannt wurde, was für "C-like Object Oriented Language" stand. Microsoft hatte erwogen, den Namen "Cool" als endgültigen Namen der Sprache beizubehalten, entschied sich aber aus markenrechtlichen Gründen dagegen. Als das .NET-Projekt auf der Professional Developers Conference im Juli 2000 öffentlich angekündigt wurde, war die Sprache bereits in C# umbenannt worden, und die Klassenbibliotheken und die ASP.NET-Laufzeitumgebung waren auf C# portiert worden.

Hejlsberg ist der Hauptentwickler und leitende Architekt von C# bei Microsoft und war zuvor an der Entwicklung von Turbo Pascal, Embarcadero Delphi (früher CodeGear Delphi, Inprise Delphi und Borland Delphi) und Visual J++ beteiligt. In Interviews und Fachbeiträgen hat er erklärt, dass Fehler in den meisten großen Programmiersprachen (z. B. C++, Java, Delphi und Smalltalk) die Grundlage für die Common Language Runtime (CLR) bildeten, die wiederum das Design der Sprache C# selbst beeinflusst hat.

James Gosling, der 1994 die Programmiersprache Java entwickelt hat, und Bill Joy, ein Mitbegründer von Sun Microsystems, dem Urheber von Java, bezeichneten C# als eine "Imitation" von Java; Gosling sagte weiter, dass "[C# ist] eine Art Java mit gestrichener Zuverlässigkeit, Produktivität und Sicherheit". Klaus Kreft und Angelika Langer (Autoren eines Buches über C++-Ströme) erklärten in einem Blogbeitrag, dass "Java und C# fast identische Programmiersprachen sind. Kaum jemand wird behaupten, dass Java oder C# revolutionäre Programmiersprachen sind, die die Art und Weise, wie wir Programme schreiben, verändert haben", und "C# hat sich viel von Java geborgt - und umgekehrt. Jetzt, wo C# Boxing und Unboxing unterstützt, werden wir eine sehr ähnliche Funktion in Java haben." Im Juli 2000 sagte Hejlsberg, dass C# "kein Java-Klon" sei und in seinem Design "viel näher an C++" liege.

Seit der Veröffentlichung von C# 2.0 im November 2005 haben sich die Sprachen C# und Java immer weiter auseinander entwickelt und sind zu zwei ganz unterschiedlichen Sprachen geworden. Eine der ersten großen Abweichungen war die Hinzufügung von Generika zu beiden Sprachen, die sehr unterschiedlich implementiert wurden. C# nutzt die Verdinglichung, um "erstklassige" generische Objekte bereitzustellen, die wie jede andere Klasse verwendet werden können, wobei die Codegenerierung zur Zeit des Ladens der Klasse erfolgt. Darüber hinaus hat C# mehrere wichtige Funktionen hinzugefügt, um die funktionale Programmierung zu unterstützen. Dies gipfelt in den LINQ-Erweiterungen, die mit C# 3.0 veröffentlicht wurden, und dem unterstützenden Framework von Lambda-Ausdrücken, Erweiterungsmethoden und anonymen Typen. Diese Funktionen ermöglichen es C#-Programmierern, funktionale Programmiertechniken, wie z. B. Closures, zu verwenden, wenn dies für ihre Anwendung von Vorteil ist. Die LINQ-Erweiterungen und die funktionalen Importe helfen den Entwicklern, die Menge an "Boilerplate"-Code zu reduzieren, der in häufigen Aufgaben wie der Abfrage einer Datenbank, dem Parsen einer XML-Datei oder dem Durchsuchen einer Datenstruktur enthalten ist, und verlagern den Schwerpunkt auf die eigentliche Programmlogik, um die Lesbarkeit und Wartbarkeit zu verbessern.

C# hatte früher ein Maskottchen namens Andy (benannt nach Anders Hejlsberg). Es wurde am 29. Januar 2004 aus dem Verkehr gezogen.

C# wurde ursprünglich dem ISO/IEC JTC 1 Unterkomitee SC 22 unter ISO/IEC 23270:2003 zur Überprüfung vorgelegt, zurückgezogen und dann unter ISO/IEC 23270:2006 genehmigt. Die 23270:2006 wird unter 23270:2018 zurückgezogen und mit dieser Version genehmigt.

Bezeichnung

Microsoft verwendete den Namen C# erstmals 1988 für eine Variante der Sprache C, die für die inkrementelle Kompilierung entwickelt wurde. Dieses Projekt wurde nicht abgeschlossen, aber der Name lebt weiter.

Cis-Musiknote

Der Name "Cis" wurde von der musikalischen Notation inspiriert, bei der das Symbol für ein Cis anzeigt, dass die geschriebene Note einen Halbton höher gesetzt werden sollte. Dies ähnelt dem Sprachnamen von C++, wo "++" anzeigt, dass eine Variable nach ihrer Auswertung um 1 erhöht werden soll. Das scharfe Symbol ähnelt auch einer Ligatur aus vier "+"-Symbolen (in einem Raster von zwei mal zwei), was ebenfalls darauf hindeutet, dass die Sprache eine Erweiterung von C++ ist.

Aufgrund technischer Beschränkungen bei der Anzeige (Standardschriftarten, Browser usw.) und der Tatsache, dass das scharfe Symbol (U+266F MUSIC SHARP SIGN ()) auf den meisten Tastaturen nicht vorhanden ist, wurde das Zahlenzeichen (U+0023 # NUMBER SIGN (#)) gewählt, um das scharfe Symbol im geschriebenen Namen der Programmiersprache anzugleichen. Diese Konvention ist in der ECMA-334 C#-Sprachenspezifikation enthalten.

Das Suffix "sharp" wurde von einer Reihe anderer .NET-Sprachen verwendet, die Varianten bestehender Sprachen sind, darunter J# (eine ebenfalls von Microsoft entwickelte .NET-Sprache, die von Java 1.1 abgeleitet ist), A# (von Ada) und die funktionale Programmiersprache F#. Die ursprüngliche Implementierung von Eiffel für .NET wurde Eiffel# genannt, ein Name, der nicht mehr verwendet wird, seit die vollständige Eiffel-Sprache unterstützt wird. Das Suffix wurde auch für Bibliotheken verwendet, wie Gtk# (ein .NET-Wrapper für GTK und andere GNOME-Bibliotheken) und Cocoa# (ein Wrapper für Cocoa).

Versionen

Version Spezifikation der Sprache Datum .NET Visuelles Studio
Ecma ISO/IEC Microsoft
C# 1.0 Dezember 2002 April 2003 Januar 2002 Januar 2002 .NET-Rahmenwerk 1.0 Visual Studio .NET 2002
C# 1.1
C# 1.2
Oktober 2003 April 2003
  • .NET-Framework 1.1
Anschauliches Studio .NET 2003
C# 2.0 Juni 2006 September 2006 September 2005 November 2005
  • .NET-Rahmenwerk 2.0
  • .NET-Framework 3.0
Anschauliches Studio 2005
Anschauliches Studio 2008
C# 3.0 Keine August 2007 November 2007
  • .NET Framework 2.0 (außer LINQ)
  • .NET-Framework 3.0 (außer LINQ)
  • .NET-Rahmenwerk 3.5
Anschauliches Studio 2008
C# 4.0 April 2010 April 2010
  • .NET-Framework 4
Visuelles Studio 2010
C# 5.0 Dezember 2017 Dezember 2018 Juni 2013 August 2012
  • .NET Framework 4.5
Visuelles Studio 2012
Visuelles Studio 2013
C# 6.0 Keine Entwurf Juli 2015
  • .NET Framework 4.6
  • .NET Core 1.0
  • .NET Core 1.1
Visuelles Studio 2015
C# 7.0 Vorschlag für die Spezifikation März 2017
  • .NET Framework 4.7
Visual Studio 2017 Version 15.0
C# 7.1 Vorschlag für die Spezifikation August 2017
  • .NET Core 2.0
Visual Studio 2017 Version 15.3
C# 7.2 Vorschlag für die Spezifikation November 2017 Visual Studio 2017 Version 15.5
C# 7.3 Vorschlag für die Spezifikation Mai 2018
  • .NET Core 2.1
  • .NET Core 2.2
  • .NET Framework 4.8
Visual Studio 2017 Version 15.7
C# 8.0 Vorschlag für die Spezifikation September 2019
  • .NET Core 3.0
  • .NET Core 3.1
Visual Studio 2019 Version 16.3
C# 9.0 Vorschlag für die Spezifikation November 2020
  • .NET 5.0
Visual Studio 2019 Version 16.8
C# 10.0 Vorschlag für die Spezifikation November 2021
  • .NET 6.0
  • .NET 6.0.1
Visual Studio 2022 Version 17.0

Syntax

Die Kernsyntax der Sprache C# ähnelt der anderer Sprachen im C-Stil, wie z. B. C, C++ und insbesondere Java:

  • Semikolons werden verwendet, um das Ende einer Anweisung zu kennzeichnen.
  • Geschweifte Klammern werden verwendet, um Anweisungen zu gruppieren. Anweisungen werden in der Regel in Methoden (Funktionen), Methoden in Klassen und Klassen in Namensräumen gruppiert.
  • Variablen werden mit einem Gleichheitszeichen zugewiesen, aber mit zwei aufeinanderfolgenden Gleichheitszeichen verglichen.
  • Eckige Klammern werden bei Arrays verwendet, sowohl um sie zu deklarieren als auch um einen Wert an einem bestimmten Index in einem Array zu erhalten.

Unterscheidende Merkmale

Einige bemerkenswerte Merkmale von C#, die es von C, C++ und Java unterscheiden, sind folgende:

Portabilität

C# ist die Programmiersprache, die die zugrunde liegende Common Language Infrastructure (CLI) am direktesten widerspiegelt. Die meisten intrinsischen Typen entsprechen den Wertetypen, die durch das CLI-Framework implementiert werden. Die Sprachspezifikation enthält jedoch keine Angaben zu den Anforderungen an die Codegenerierung durch den Compiler, d. h. es ist nicht festgelegt, dass ein C#-Compiler eine Common Language Runtime ansteuern oder eine Common Intermediate Language (CIL) oder ein anderes spezifisches Format generieren muss. Theoretisch könnte ein C#-Compiler Maschinencode wie traditionelle C++- oder Fortran-Compiler erzeugen.

Typisierung

C# unterstützt stark, implizit typisierte Variablendeklarationen mit dem Schlüsselwort var und implizit typisierte Arrays mit dem Schlüsselwort new[] gefolgt von einem Collection-Initialisierer.

C# unterstützt einen streng booleschen Datentyp, bool. Anweisungen, die Bedingungen einbeziehen, wie while und if, erfordern einen Ausdruck eines Typs, der den Wahrheitsoperator implementiert, wie der Typ Boolean. C++ hat zwar auch einen Boolean-Typ, dieser kann aber frei in und aus Integern konvertiert werden, und Ausdrücke wie if (a) erfordern nur, dass a in bool konvertierbar ist, so dass a ein int oder ein Zeiger sein kann. C# verbietet diesen "integer meaning true or false"-Ansatz mit der Begründung, dass der Zwang zur Verwendung von Ausdrücken, die genau bool zurückgeben, bestimmte Arten von Programmierfehlern wie if (a = b) verhindern kann (Verwendung der Zuweisung = anstelle von equality ==).

C# ist typsicherer als C++. Die einzigen impliziten Konvertierungen, die standardmäßig vorgenommen werden, sind diejenigen, die als sicher gelten, wie z. B. die Erweiterung von Ganzzahlen. Dies wird zur Kompilierzeit, während des JIT und in einigen Fällen auch zur Laufzeit erzwungen. Es finden keine impliziten Konvertierungen zwischen Booleschen und ganzen Zahlen oder zwischen Aufzählungselementen und ganzen Zahlen statt (mit Ausnahme des Literals 0, das implizit in einen beliebigen Aufzählungstyp konvertiert werden kann). Jede benutzerdefinierte Konvertierung muss explizit als explizit oder implizit gekennzeichnet werden, im Gegensatz zu C++ Kopierkonstruktoren und Konvertierungsoperatoren, die beide standardmäßig implizit sind.

C# hat explizite Unterstützung für Kovarianz und Kontravarianz in generischen Typen, im Gegensatz zu C++, das ein gewisses Maß an Unterstützung für Kontravarianz einfach durch die Semantik von Rückgabetypen auf virtuellen Methoden hat.

Aufzählungsmitglieder werden in ihren eigenen Bereich gestellt.

Die Sprache C# lässt keine globalen Variablen oder Funktionen zu. Alle Methoden und Mitglieder müssen innerhalb von Klassen deklariert werden. Statische Mitglieder von öffentlichen Klassen können globale Variablen und Funktionen ersetzen.

Lokale Variablen können im Gegensatz zu C und C++ keine Variablen des umschließenden Blocks überschatten.

Metaprogrammierung

Metaprogrammierung kann auf verschiedene Weise erreicht werden:

  • Reflection wird durch .NET-APIs unterstützt, die Szenarien wie die Überprüfung von Typ-Metadaten und dynamische Methodenaufrufe ermöglichen.
  • Ausdrucksbäume stellen Code als abstrakten Syntaxbaum dar, bei dem jeder Knoten ein Ausdruck ist, der inspiziert oder ausgeführt werden kann. Dies ermöglicht eine dynamische Änderung des ausführbaren Codes zur Laufzeit. Ausdrucksbäume führen eine gewisse Homoikonizität in die Sprache ein.
  • Attribute sind Metadaten, die an Typen, Member oder ganze Assemblies angehängt werden können, was den Annotationen in Java entspricht. Attribute sind sowohl für den Compiler als auch für den Code durch Reflexion zugänglich. Viele dieser Attribute duplizieren die Funktionalität der plattformabhängigen Präprozessoranweisungen von GCC und VisualC++.
  • Die .NET Compiler Platform (Roslyn) bietet API-Zugang zu Sprachkompilierungsdiensten und ermöglicht die Kompilierung von C#-Code aus .NET-Anwendungen heraus. Sie stellt APIs für die syntaktische (lexikalische) Analyse von Code, die semantische Analyse, die dynamische Kompilierung zu CIL und die Code-Emission zur Verfügung.
  • Quellgeneratoren, eine Funktion des Roslyn C#-Compilers, ermöglichen die Metaprogrammierung während der Kompilierung. Während des Kompilierungsprozesses können Entwickler den zu kompilierenden Code mit der API des Compilers überprüfen und zusätzlich generierten C#-Quellcode zur Kompilierung übergeben.

Methoden und Funktionen

Eine Methode in C# ist ein Mitglied einer Klasse, das als Funktion (eine Folge von Anweisungen) aufgerufen werden kann, und nicht die bloße Fähigkeit einer Klasseneigenschaft, einen Wert zu halten. Wie in anderen syntaktisch ähnlichen Sprachen wie C++ und ANSI C ist die Signatur einer Methode eine Deklaration, die in dieser Reihenfolge Folgendes umfasst: alle optionalen Zugriffsschlüsselwörter (z. B. private), die explizite Angabe des Rückgabetyps (z. B. int oder das Schlüsselwort void, wenn kein Wert zurückgegeben wird), den Namen der Methode und schließlich eine in Klammern gesetzte Folge von durch Kommata getrennten Parameterspezifikationen, die jeweils aus dem Typ eines Parameters, seinem formalen Namen und optional einem Standardwert bestehen, der zu verwenden ist, wenn keiner angegeben wird. Bestimmte Arten von Methoden, z. B. solche, die lediglich eine Klasseneigenschaft durch Rückgabewert oder Zuweisung erhalten oder setzen, erfordern keine vollständige Signatur, aber im allgemeinen Fall enthält die Definition einer Klasse die vollständige Signaturdeklaration ihrer Methoden.

Wie bei C++ und im Gegensatz zu Java müssen C#-Programmierer das Scope-Modifizierungsschlüsselwort virtual verwenden, damit Methoden von Unterklassen überschrieben werden können.

Erweiterungsmethoden in C# ermöglichen es Programmierern, statische Methoden so zu verwenden, als wären sie Methoden aus der Methodentabelle einer Klasse, so dass Programmierer einem Objekt Methoden hinzufügen können, die ihrer Meinung nach für dieses Objekt und seine Derivate existieren sollten.

Der dynamische Typ ermöglicht die Bindung von Methoden zur Laufzeit, wodurch JavaScript-ähnliche Methodenaufrufe und die Komposition von Objekten zur Laufzeit ermöglicht werden.

C# unterstützt stark typisierte Funktionszeiger über das Schlüsselwort delegate. Wie die Pseudo-C++-Signale und -Slots des Qt-Frameworks verfügt C# über eine Semantik, die speziell Ereignisse im Stil von Publish-Subscribe umgibt, auch wenn C# dazu Delegates verwendet.

C# bietet Java-ähnliche synchronisierte Methodenaufrufe über das Attribut [MethodImpl(MethodImplOptions.Synchronized)] und hat Unterstützung für sich gegenseitig ausschließende Sperren über das Schlüsselwort lock.

Eigenschaft

C# unterstützt Klassen mit Eigenschaften. Die Eigenschaften können einfache Accessor-Funktionen mit einem Backing-Feld sein, oder Getter- und Setter-Funktionen implementieren.

Seit C# 3.0 gibt es den syntaktischen Zucker der auto-implementierten Eigenschaften, bei denen der Accessor (Getter) und Mutator (Setter) Operationen auf ein einzelnes Attribut einer Klasse kapseln.

Namespace

Ein C#-Namensraum bietet den gleichen Grad an Code-Isolierung wie ein Java-Paket oder ein C++ Namespacemit sehr ähnlichen Regeln und Funktionen wie ein Paket. Namespaces können mit der "using"-Syntax importiert werden.

Speicherzugriff

In C# können Speicheradresszeiger nur innerhalb von Blöcken verwendet werden, die ausdrücklich als unsicher gekennzeichnet sind, und Programme mit unsicherem Code benötigen zur Ausführung entsprechende Berechtigungen. Der meiste Objektzugriff erfolgt über sichere Objektreferenzen, die immer entweder auf ein "lebendes" Objekt zeigen oder den wohldefinierten Nullwert haben; es ist unmöglich, eine Referenz auf ein "totes" Objekt (eines, das bereits gelöscht wurde) oder auf einen beliebigen Speicherblock zu erhalten. Ein unsicherer Zeiger kann auf eine Instanz eines "nicht verwalteten" Wertetyps verweisen, der keine Verweise auf "Garbage Collected"-Objekte, Arrays, Strings oder einen Block des vom Stack zugewiesenen Speichers enthält. Code, der nicht als unsicher gekennzeichnet ist, kann immer noch Zeiger über den Typ System.IntPtr speichern und manipulieren, aber er kann sie nicht derefenzieren.

Verwalteter Speicher kann nicht explizit freigegeben werden; stattdessen wird er automatisch zu Garbage Collection zusammengefasst. Die Garbage Collection behebt das Problem von Speicherlecks, indem sie den Programmierer von der Verantwortung für die Freigabe von Speicher befreit, der in den meisten Fällen nicht mehr benötigt wird. Code, der Verweise auf Objekte länger als erforderlich beibehält, kann immer noch einen höheren Speicherverbrauch als nötig haben, aber sobald der letzte Verweis auf ein Objekt freigegeben ist, steht der Speicher für die Garbage Collection zur Verfügung.

Ausnahmen

Dem Programmierer steht eine Reihe von Standardausnahmen zur Verfügung. Methoden in Standardbibliotheken lösen unter bestimmten Umständen regelmäßig Systemausnahmen aus, und die Bandbreite der Ausnahmen, die ausgelöst werden, ist normalerweise dokumentiert. Für Klassen können benutzerdefinierte Ausnahmeklassen definiert werden, die je nach Bedarf eine spezifische Behandlung für bestimmte Umstände ermöglichen.

Geprüfte Ausnahmen gibt es in C# nicht (im Gegensatz zu Java). Dies ist eine bewusste Entscheidung, die auf den Aspekten der Skalierbarkeit und Versionierbarkeit beruht.

Polymorphie

Im Gegensatz zu C++ unterstützt C# keine Mehrfachvererbung, obwohl eine Klasse eine beliebige Anzahl von "Schnittstellen" (vollständig abstrakte Klassen) implementieren kann. Dies war eine Designentscheidung des leitenden Architekten der Sprache, um Komplikationen zu vermeiden und die architektonischen Anforderungen in der gesamten CLI zu vereinfachen.

Bei der Implementierung mehrerer Schnittstellen, die eine Methode mit demselben Namen enthalten und Parameter desselben Typs in derselben Reihenfolge (d. h. dieselbe Signatur) annehmen, erlaubt C# ähnlich wie Java sowohl eine einzige Methode, die alle Schnittstellen abdeckt, als auch, falls erforderlich, spezifische Methoden für jede Schnittstelle.

Im Gegensatz zu Java unterstützt C# jedoch das Überladen von Operatoren.

Sprachintegrierte Abfrage (LINQ)

C# hat die Möglichkeit, LINQ durch das .NET Framework zu nutzen. Ein Entwickler kann eine Vielzahl von Datenquellen abfragen, sofern die Schnittstelle IEnumerable<T> auf dem Objekt implementiert ist. Dazu gehören XML-Dokumente, ein ADO.NET-Datensatz und SQL-Datenbanken.

Die Verwendung von LINQ in C# bringt Vorteile wie Intellisense-Unterstützung, starke Filterfunktionen, Typsicherheit mit Kompilierfehlerprüfung und Konsistenz bei der Abfrage von Daten aus verschiedenen Quellen. Es gibt verschiedene Sprachstrukturen, die mit C# und LINQ verwendet werden können: Abfrageausdrücke, Lambda-Ausdrücke, anonyme Typen, implizit typisierte Variablen, Erweiterungsmethoden und Objektinitialisierungen.

Funktionale Programmierung

Obwohl es sich in erster Linie um eine imperative Sprache handelt, bot C# 2.0 eine begrenzte Unterstützung für die funktionale Programmierung durch Funktionen erster Klasse und Abschlüsse in Form von anonymen Delegaten. C# 3.0 erweiterte die Unterstützung für funktionale Programmierung mit der Einführung einer leichtgewichtigen Syntax für Lambda-Ausdrücke, Erweiterungsmethoden (eine Möglichkeit für Module) und einer Syntax für das Verstehen von Listen in Form einer "Abfrageverstehenssprache". C# 7.0 fügt Funktionen hinzu, die typisch für funktionale Sprachen sind, wie Tupel, lokale Funktionen und Mustervergleiche. C# 9.0 führt die Record-Funktion ein, die in erster Linie für eine bessere Unterstützung unveränderlicher Datenmodelle gedacht ist.

Einheitliches Typsystem

C# hat ein vereinheitlichtes Typsystem. Dieses einheitliche Typsystem wird Common Type System (CTS) genannt.

Ein vereinheitlichtes Typsystem impliziert, dass alle Typen, einschließlich Primitive wie Integer, Unterklassen der System.Object Klasse sind. Zum Beispiel erbt jeder Typ eine ToString() Methode.

Kategorien von Datentypen

Das CTS unterteilt Datentypen in zwei Kategorien:

  1. Referenztypen
  2. Wertetypen

Instanzen von Wertetypen haben weder eine referenzielle Identität noch eine referenzielle Vergleichssemantik. Gleichheits- und Ungleichheitsvergleiche für Wertetypen vergleichen die tatsächlichen Datenwerte innerhalb der Instanzen, sofern die entsprechenden Operatoren nicht überladen sind. Wertetypen sind abgeleitet von System.ValueTypeabgeleitet, haben immer einen Standardwert und können immer erstellt und kopiert werden. Weitere Einschränkungen für Werttypen sind, dass sie nicht voneinander abgeleitet werden können (aber Schnittstellen implementieren können) und keinen expliziten Standardkonstruktor (ohne Parameter) haben können. Beispiele für Werttypen sind alle primitiven Typen, wie int (eine vorzeichenbehaftete 32-Bit-Ganzzahl), float (eine 32-Bit-IEEE-Gleitkommazahl), char (eine 16-Bit-Unicode-Codeeinheit) und System.DateTime (identifiziert einen bestimmten Zeitpunkt mit Nanosekundengenauigkeit). Andere Beispiele sind enum (Aufzählungen) und struct (benutzerdefinierte Strukturen).

Im Gegensatz dazu haben Referenztypen den Begriff der referentiellen Identität, was bedeutet, dass sich jede Instanz eines Referenztyps von jeder anderen Instanz unterscheidet, selbst wenn die Daten in beiden Instanzen gleich sind. Dies spiegelt sich in den standardmäßigen Gleichheits- und Ungleichheitsvergleichen für Referenztypen wider, die eher auf referenzielle als auf strukturelle Gleichheit testen, es sei denn, die entsprechenden Operatoren sind überladen (wie im Fall von System.String). Einige Operationen sind nicht immer möglich, z. B. das Erstellen einer Instanz eines Referenztyps, das Kopieren einer vorhandenen Instanz oder das Durchführen eines Wertevergleichs für zwei vorhandene Instanzen. Obwohl bestimmte Referenztypen solche Dienste anbieten können, indem sie einen öffentlichen Konstruktor bereitstellen oder eine entsprechende Schnittstelle implementieren (z. B. ICloneable oder IComparable). Beispiele für Referenztypen sind Objekt (die ultimative Basisklasse für alle anderen C#-Klassen), System.String (eine Zeichenkette aus Unicode-Zeichen), und System.Array (eine Basisklasse für alle C#-Arrays).

Beide Typenkategorien sind durch benutzerdefinierte Typen erweiterbar.

Boxing und Unboxing

Boxing ist die Umwandlung eines Objekts vom Typ Wert in einen Wert vom entsprechenden Referenztyp. Boxing in C# ist implizit.

Unter Unboxing versteht man die Umwandlung eines Wertes eines Referenztyps (der zuvor geboxt wurde) in einen Wert eines Werttyps. Unboxing in C# erfordert einen expliziten Typ-Cast. Ein boxed Objekt vom Typ T kann nur in ein T (oder ein nullable T) unboxed werden.

Beispiel:

int foo = 42; // Werttyp.
object bar = foo; // foo ist mit bar verschränkt.
int foo2 = (int)bar; // Unboxed zurück zum Wertetyp. <span title="Aus: Englische Wikipedia, Abschnitt &quot;Boxing and unboxing&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/C_Sharp_(programming_language)#Boxing_and_unboxing <span style="color:#dddddd">ⓘ</span>]</span>

Bibliotheken

In der C#-Spezifikation ist ein Mindestsatz an Typen und Klassenbibliotheken festgelegt, die der Compiler zur Verfügung haben sollte. In der Praxis wird C# am häufigsten mit einer Implementierung der Common Language Infrastructure (CLI) verwendet, die als ECMA-335 Common Language Infrastructure (CLI) standardisiert ist.

Zusätzlich zu den Standard-CLI-Spezifikationen gibt es viele kommerzielle und Community-Klassenbibliotheken, die auf den Bibliotheken des .NET-Frameworks aufbauen und zusätzliche Funktionen bieten.

C# kann jede in der Liste der .NET-Bibliotheken und -Frameworks enthaltene Bibliothek aufrufen.

Beispiele

Hallo Welt

Das folgende ist ein sehr einfaches C#-Programm, eine Version des klassischen "Hello World"-Beispiels, das die in C# 9 eingeführte Funktion der Top-Level-Anweisungen verwendet:

using System; <span title="Aus: Englische Wikipedia, Abschnitt &quot;Hello World&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/C_Sharp_(programming_language)#Hello_World <span style="color:#dddddd">ⓘ</span>]</span>

Console.WriteLine("Hallo, Welt!");

Bei Code, der in C# 8 oder niedriger geschrieben wurde, muss die Einstiegslogik eines Programms in einer Main-Methode innerhalb eines Typs geschrieben werden:

using System; <span title="Aus: Englische Wikipedia, Abschnitt &quot;Hello World&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/C_Sharp_(programming_language)#Hello_World <span style="color:#dddddd">ⓘ</span>]</span>

// Eine Version des klassischen "Hello World"-Programms
class Programm
{
    static void Main()
    {
        Console.WriteLine("Hallo, Welt!");
    }
}

Mit diesem Code wird dieser Text im Konsolenfenster angezeigt:

Hallo, Welt! 

Jede Zeile hat einen Zweck:

using System; <span title="Aus: Englische Wikipedia, Abschnitt &quot;Hello World&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/C_Sharp_(programming_language)#Hello_World <span style="color:#dddddd">ⓘ</span>]</span>

Die obige Zeile importiert alle Typen im Namespace System. Die Klasse Console, die später im Quellcode verwendet wird, ist beispielsweise im System-Namensraum definiert, d. h. sie kann verwendet werden, ohne den vollständigen Namen des Typs (der den Namensraum enthält) anzugeben.

// Eine Version des klassischen "Hello World"-Programms

Diese Zeile ist ein Kommentar; sie beschreibt und dokumentiert den Code für den/die Programmierer.

Klasse Programm <span title="Aus: Englische Wikipedia, Abschnitt &quot;Hello World&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/C_Sharp_(programming_language)#Hello_World <span style="color:#dddddd">ⓘ</span>]</span>

Oben ist eine Klassendefinition für das Programm Klasse. Alles, was zwischen den beiden geschweiften Klammern folgt, beschreibt diese Klasse.

{
    ...
}

Die geschweiften Klammern markieren die Grenzen eines Codeblocks. In diesem ersten Fall markieren sie den Anfang und das Ende der Programm Klasse.

static void Main() <span title="Aus: Englische Wikipedia, Abschnitt &quot;Hello World&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/C_Sharp_(programming_language)#Hello_World <span style="color:#dddddd">ⓘ</span>]</span>

Hier wird die Methode der Klasse deklariert, mit der die Ausführung des Programms beginnt. Die .NET-Laufzeit ruft die Methode Main Methode auf. Anders als in Java benötigt die Main Methode nicht die öffentliche Schlüsselwort, das dem Compiler mitteilt, dass die Methode von jeder Klasse aus aufgerufen werden kann. Schreiben von static void Main(string[] args) ist gleichbedeutend mit dem Schreiben von private static void Main(string[] args). Das Schlüsselwort static macht die Methode ohne eine Instanz von Programm. Der Einstiegspunkt jeder Konsolenanwendung Main Einstiegspunkt jeder Konsolenanwendung muss deklariert werden statisch deklariert werden, sonst würde das Programm eine Instanz von Programmerfordern, aber jede Instanz würde ein Programm erfordern. Um diese unauflösbare zirkuläre Abhängigkeit zu vermeiden, melden C#-Compiler, die Konsolenanwendungen (wie die oben genannte) verarbeiten, einen Fehler, wenn es keine statische Main Methode gibt. Die void Schlüsselwort deklariert, dass Main keinen Rückgabewert hat.

Console.WriteLine("Hallo, Welt!"); <span title="Aus: Englische Wikipedia, Abschnitt &quot;Hello World&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/C_Sharp_(programming_language)#Hello_World <span style="color:#dddddd">ⓘ</span>]</span>

In dieser Zeile wird die Ausgabe geschrieben. Konsole ist eine statische Klasse in der System Namespace. Sie bietet eine Schnittstelle zu den Standard-Eingabe-, Ausgabe- und Fehlerströmen für Konsolenanwendungen. Das Programm ruft die Konsole Methode auf. WriteLineauf, die auf der Konsole eine Zeile mit dem Argument anzeigt, die Zeichenkette "Hallo, Welt!".

GUI

Ein Beispiel für eine Windows-GUI:

using System;
using System.Windows.Forms; <span title="Aus: Englische Wikipedia, Abschnitt &quot;GUI&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/C_Sharp_(programming_language)#GUI <span style="color:#dddddd">ⓘ</span>]</span>

class Programm
{
    static void Main()
    {
        MessageBox.Show("Hallo, Welt!");
        Console.WriteLine("Ist fast das gleiche Argument!");
    }
}

Dieses Beispiel ähnelt dem vorherigen Beispiel, mit dem Unterschied, dass es ein Dialogfeld erzeugt, das die Nachricht "Hallo, Welt!" enthält, anstatt sie auf die Konsole zu schreiben.

Bilder

Eine weitere nützliche Bibliothek ist die System.Drawing-Bibliothek, die zum programmgesteuerten Zeichnen von Bildern verwendet wird. Ein Beispiel:

using System;
using System.Drawing; <span title="Aus: Englische Wikipedia, Abschnitt &quot;Images&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/C_Sharp_(programming_language)#Images <span style="color:#dddddd">ⓘ</span>]</span>

public class Beispiel
{
    public static Bild img; <span title="Aus: Englische Wikipedia, Abschnitt &quot;Images&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/C_Sharp_(programming_language)#Images <span style="color:#dddddd">ⓘ</span>]</span>

    static void Main()
    {
        img = Image.FromFile("Image.png");
    }
}

Damit wird ein Bild erstellt, das mit dem in "Image.png" gespeicherten Bild identisch ist.

Standardisierung und Lizenzierung

Im August 2001 reichten Microsoft, Hewlett-Packard und Intel gemeinsam Spezifikationen für C# und die Common Language Infrastructure (CLI) bei der Standardisierungsorganisation Ecma International ein. Im Dezember 2001 veröffentlichte die ECMA die ECMA-334 C#-Sprachenspezifikation. C# wurde 2003 zu einer ISO/IEC-Norm (ISO/IEC 23270:2003 - Informationstechnologie - Programmiersprachen - C#). Zuvor hatte die ECMA im Dezember 2002 gleichwertige Spezifikationen als 2. Im Juni 2005 genehmigte die ECMA die 3. Ausgabe der C#-Spezifikation und aktualisierte ECMA-334. Zu den Neuerungen gehören partielle Klassen, anonyme Methoden, löschbare Typen und Generics (ähnlich wie bei C++ Templates). Im Juli 2005 reichte die ECMA die Standards und die zugehörigen TRs bei ISO/IEC JTC 1/SC 22 über dessen Fast-Track-Verfahren ein. Dieser Prozess dauert normalerweise 6-9 Monate.

Die C#-Sprachdefinition und die CLI sind im Rahmen von ISO/IEC- und ECMA-Standards standardisiert, die einen angemessenen und nicht diskriminierenden Lizenzschutz vor Patentansprüchen bieten.

Microsoft hat sich zunächst bereit erklärt, Open-Source-Entwickler nicht wegen der Verletzung von Patenten in gemeinnützigen Projekten für den Teil des Frameworks zu verklagen, der unter den OSP fällt. Microsoft hat sich auch bereit erklärt, Patente, die sich auf Novell-Produkte beziehen, nicht gegen zahlende Kunden von Novell durchzusetzen, mit Ausnahme einer Liste von Produkten, in denen C#, .NET oder die Novell-Implementierung von .NET (das Mono-Projekt) nicht ausdrücklich erwähnt werden. Novell behauptete jedoch, dass Mono keine Microsoft-Patente verletze. Microsoft verpflichtete sich außerdem ausdrücklich, keine Patentrechte im Zusammenhang mit dem Moonlight-Browser-Plugin geltend zu machen, das von Mono abhängt, sofern es über Novell bezogen wird.

Ein Jahrzehnt später begann Microsoft mit der Entwicklung freier, quelloffener und plattformübergreifender Werkzeuge für C#, nämlich Visual Studio Code, .NET Core und Roslyn. Mono kam zu Microsoft als ein Projekt von Xamarin, einer Microsoft-Tochtergesellschaft.

Die ECMA-Spezifikation 334 deckt nur die Sprache C# ab. Programme, die in C# geschrieben werden, nutzen gewöhnlich das .NET-Framework, das teilweise durch andere Spezifikationen beschrieben wird und teilweise proprietär ist. Dennoch ist die Sprache C# prinzipiell plattformunabhängig. Das von Ximian (jetzt Xamarin) initiierte Projekt Mono ermöglicht beispielsweise auch Nutzern von macOS oder Unix, C# für Entwicklungen auf ihrem Betriebssystem einzusetzen.

Microsoft veröffentlichte die dritte Version von C# mit dem .NET-SDK 2.0 und Visual Studio 2005 im November 2005.

Microsoft stellte klar, dass C#, genauso wie andere .NET-Sprachen, einen wichtigen Bestandteil seiner Softwarestrategie sowohl für den internen als auch für den externen Gebrauch darstelle. Das Unternehmen übernimmt eine aktive Rolle in der Vermarktung der Sprache als Teil seiner gesamten Geschäftsstrategie.

Implementierungen

Microsoft ist federführend bei der Entwicklung von Open-Source-Referenz-C#-Compilern und -Tools. Der erste Compiler, Roslyn, kompiliert in eine Zwischensprache (IL), und der zweite, RyuJIT, ist ein JIT-Compiler (Just-in-Time-Compiler), der dynamisch ist und eine fliegende Optimierung vornimmt und die IL in nativen Code für das Front-End der CPU kompiliert. RyuJIT ist quelloffen und in C++ geschrieben. Roslyn ist vollständig in verwaltetem Code (C#) geschrieben, wurde geöffnet und die Funktionalität als APIs zur Verfügung gestellt. So können Entwickler Refactoring- und Diagnosetools erstellen. Zwei Zweige der offiziellen Implementierung sind .NET Framework (Closed-Source, nur für Windows) und .NET Core (Open-Source, plattformübergreifend); sie wurden schließlich zu einer Open-Source-Implementierung zusammengeführt: .NET 5.0. Mit .NET Framework 4.6 wurde der erste Compiler durch einen neuen JIT-Compiler ersetzt.

Andere C#-Compiler (von denen einige eine Implementierung der Common Language Infrastructure und .NET-Klassenbibliotheken enthalten):

  • Mono, ein von Microsoft gefördertes Projekt, bietet einen Open-Source-C#-Compiler, eine vollständige Open-Source-Implementierung der CLI (einschließlich der erforderlichen Framework-Bibliotheken, wie sie in der ECMA-Spezifikation aufgeführt sind) und eine nahezu vollständige Implementierung der .NET-Klassenbibliotheken bis zu .NET Framework 3.5.
  • Die Elements-Toolkette von RemObjects umfasst RemObjects C#, das C#-Code in die Common Intermediate Language von .NET, Java Bytecode, Cocoa, Android Bytecode, WebAssembly und nativen Maschinencode für Windows, macOS und Linux kompiliert.
  • Das (inzwischen eingestellte) DotGNU-Projekt bot auch einen Open-Source-C#-Compiler, eine fast vollständige Implementierung der Common Language Infrastructure einschließlich der erforderlichen Rahmenbibliotheken, wie sie in der ECMA-Spezifikation erscheinen, und eine Teilmenge einiger der verbleibenden proprietären .NET-Klassenbibliotheken von Microsoft bis zu .NET 2.0 (die nicht dokumentiert oder in der ECMA-Spezifikation enthalten sind, aber in der Standarddistribution von Microsofts .NET Framework enthalten sind).

Die Unity-Spielengine verwendet C# als primäre Skriptsprache. Die Godot-Spielengine hat dank einer Spende von 24.000 $ von Microsoft ein optionales C#-Modul implementiert.

In der Regel übersetzen die C# Compiler nicht unmittelbar in die Maschinensprache, sondern in eine Zwischensprache. Bei der Ausführung wird dann eine virtuelle Maschine gestartet, die den zweiten Teil des Übersetzungsprozesses in einem Just-In-Time Compiler erledigt.

Es existieren vier Compiler für C#:

  • der von Microsoft für die neuesten Versionen von C# und Visual Basic .NET entwickelte Roslyn-Compiler (Windows; FLOSS) als neuste Iteration der .NET Compiler Platform (deren ältere Versionen proprietäre Software waren)
  • mcs von Xamarin für Mono (Windows, macOS, GNU/Linux; FLOSS) unterstützte bis C# Version 6 alle Features, die Version 7 wurde nur noch partiell unterstützt
  • DotGNU (FLOSS), Weiterentwicklung wurde 2012 eingestellt.
  • CoreRT/.Net Native

Namensgebung

C# wurde unter dem Codenamen Cool entwickelt, der jedoch aus Gründen des Marketings zur Veröffentlichung geändert wurde. Der Name C Sharp leitet sich vom Zeichen Kreuz (, englisch sharp) der Notenschrift ab, was dort für eine Erhöhung des Grundtons um einen Halbton steht. C sharp ist also der englische Begriff für den Ton cis. Dies ist eine Anspielung darauf, dass der Name der Programmiersprache C++ der Notation für die Erhöhung des Werts einer Variable um eins entstammt. Des Weiteren kann man das Kreuz-Zeichen als Kombination von vier Plus-Zeichen betrachten, was eine Erhöhung von C++ darstellen soll. Allerdings enthält der Name nicht das Kreuz-Zeichen der Musiknotation, sondern ein Doppelkreuz bzw. Raute, das häufig als Ersatzzeichen für das Kreuz genutzt wird, weil es im Gegensatz zum Kreuz auf üblichen Tastaturen vorkommt.

In künstlerischen Darstellungen wird teilweise auch das Notenschriftzeichen verwendet, was in der Folge von einigen für korrekt gehalten wird. Eindeutig falsch ist die zweifache Verwendung des doppelten Dagger-Zeichens.

Sprachderivate

  • Sing#
  • Spec#
  • Vala für Programme des Gnome-Projektes