Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs

Datentypen in C#

Geschrieben von: Christian Holm
Kategorie: C#

This printed page brought to you by AlphaSierraPapa

In diesem Artikel möchte ich Ihnen die Datentypen von C# (sprich "C sharp") erklären. Obwohl C# mit C++ verwandt ist, hat sich auch einiges in der Definition und in der Behandlung der Datentypen geändert. So einfach sich dieses Thema vielleicht auch anhören mag, Datentypen stellen unter anderem die Grundstruktur eines Programmes dar, und können bei falscher Implementation zu ärgerlichen Compilerfehlern führen.

Anmerkung: Dadurch daß in C#, wie auch in C++, der Sourcecode in Englisch gehalten ist, werde ich die sprachspezifischen Befehle, Schlüsselwörter etc., unverändert lassen und gegebenfalls das deutsche Äquivalent verwenden; z.B. floating point- / Fließkomma-.

Einteilung der Datentypen

Grundsätzlich lassen sich die Datentypen wie folgt in drei Kategorien einteilen:

Anmerkung zu "pointer-types": Diese Typen können nur im sogenannten Unsafe Code verwendet werden. Pointer (Zeiger) beinhalten Adressen zu Speicherorten. Da in dieser Hinsicht in C# Vereinfachungen für den Entwickler getroffen wurden (u. a. der Garbage Collector, kurz GC, der nun die Speicherverwaltung über hat) sollten diese nur mehr eingeschränkt verwendet werden, um Kollisionen mit geschütztem Speicherbereich oder "Exception Errors" zu vermeiden.

Der Unterschied zwischen value-types und reference-types liegt darin, daß value-types die tatsächlichen Daten enthalten und reference-types einen Bezug auf die Daten beinhalten.
Mit den reference-types ist es z.B. möglich, daß zwei Variablen sich auf ein und dasselbe Objekt beziehen. Damit ist man in der Lage das Objekt mit der einen Variable manipulieren, während die Änderung in beiden Variablen sichtbar ist.

Da jeder value-type eine eigene Kopie der Daten besitzt, können Manipulationen an der einen Variable die andere nicht beeinflußen.

Value-Types

Dieser Datentyp ist entweder ein struct-Typ oder ein enumeration-Typ. C# enthält vordefinierte struct-types welche auch simple-types genannt werden. Eine Variable enthält immer einen Wert im Datentyp der ihr zugewiesen wurde. Bevor Sie in C# eine Variable verwenden können, müssen Sie diese zwingend vorher deklarieren.

In C# werden die Variablen-Typen nun eingeteilt in:

Besprechen wir nun die simple-types: Diese unterteilen sich in

Die wichtigsten Datentypen seien hier ausführlicher beschrieben:

Integral Types

In C# gibt es neun integral-types: byte, sbyte, short, ushort, int, uint, long und ulong. Der Typ char soll später extra beschrieben werden. Die aufgezählten Datentypen haben folgende Eigenschaften:

Daten-Typ Gültigkeitsbereich Bitgröße
byte 0 bis 255 Unsigned 8-bit integer
sbyte -128 bis 127 Signed 8-bit Integer
short -32.768 bis 32.767 Signed 16-bit Integer
ushort 0 bis 65.535 Unsigned 16-bit Integer
int -2.147.483.648 bis 2.147.483.647 Signed 32-bit Integer
uint 0 bis 4.294.967.295 Unsigned 32-bit Integer
long –9.223.372.036.854.775.808 bis 9.223.372.036.854.775.807 Signed 64-bit Integer
ulong 0 bis 18.446.744.073.709.551.615 Unsigned 64-bit Integer
char U+0000 bis U+ffff Unicode 16-bit Zeichen

Beachte: Wie Ihnen sicher schon aufgefallen ist, haben integer und long andere Gültigkeitsbereiche als in C++. In C# ist integer nicht mehr von einem word abhängig und long hat jetzt eine Bitgröße von 64 bit.

Decimal Type

Der Decimal Datentyp hat eine Größe von 128 Bit. Er weist also eine hohe Genauigkeit gegenüber dem floating point-type auf, hat aber im Vergleich zum floating point-type einen engeren Gültigkeitsbereich. Dieser Datentyp ist dienlich für finanzmathematische Berechungen oder Währungsumrechungen. Der Gültigkeitsbereich geht von 1,0 * 10^-28 bis 7,9 * 10^28 mit 28-29 signifikanten Stellen.

Beachte: Die Genauigkeit ist in signifikanten Stellen gegeben und nicht in Dezimalstellen.

Rechenoperationen sind bis zu 28 Dezimalstellen genau. Auf Grund der besprochenen Unterschiede zwischen decimal und floating-point sollten sie auch vorsichtig beim umcasten (umwandeln) in die anderen Typen sein. Denn in die eine Richtung generieren sie möglicherweise einen Überlauf, in die andere verlieren Sie die Genauigkeit.

Bei der Variablendeklaration ist folgendes zu beachten: Wenn Sie bei decimal Kommastellen benutzen wollen, so müssen Sie das mit einem m als Suffix angeben.

Beispiel: decimal Wert = 3.4m; (Im C# Source Code gilt: Im Englischen gilt der Punkt als Komma!) Falls Sie den Suffix nicht angeben, wird die Variable vom Compiler als double behandelt

floating point Types

Es gibt hierbei zwei unterschiedliche Typen float und double. Wie nicht anders zu erwarten unterscheiden sie sich im Gültigkeitsbereich und in der Genauigkeit.

Daten-Typ Gültigkeitsbereich Genauigkeit
float 1.5*10^-45 bis 3.4*10^38 7 stellig
double 5*10^-324 bis 1.7*10^308 15 bis 16 stellig

bool Type

Dieser verdient in C# Beachtung: im Gegensatz zu C++ sind boolsche Datentypen und Integer Datentypen nicht mehr ident! Das heißt, der boolsche Datentyp umfaßt nur mehr die Werte true oder false, und nicht mehr Null (0) oder einen von Null (0) ungleichen Wert.

char Type

Dieser Datentyp stellt ein Zeichen im Unicodeformat dar. Ein Unicodezeichen hat eine Größe von 16 bit und ist für die meisten Sprachen verwendbar. Um einer char-Variablen einen Wert zuzuweisen, geht man so vor, daß man den Buchstaben mit einfachen Anführungszeichen umgibt.

In C# sieht dies dann so aus:

char Variablenname = 'Unicode Zeichen';  // z.B char zeichen='C';

Zwei weitere Darstellungsmöglichkeiten für Unicode Zeichen sollen hier nur am Rande erwähnt werden - die Möglichkeit der

Beachte: Wenn Sie den char Datentyp umcasten wollen, müssen Sie das auch explizit tun (im Gegensatz zu C++), indem sie eine extra Anweisung schreiben.

struct Type

Ein struct Datentyp kann Konstanten, Felder, Methoden, Eigenschaften, Indexer, etc. deklarieren. Anders als in C++ werden in C# structs als Wert aufgefaßt und Klassen als Referenztyp. Der Grundgedanke bei der Verwendung von struct ist, daß man damit "Objekte" erstellt, die wesentlich weniger Speicherplatz als echte Objekte benötigen. Das kommt dadurch, daß keine zusätzliche Speicherreferenzen benötigt werden wie für Klassen.

enumeration Type

Wenn Sie einen spezielle Datentyp suchen, der eine Reihe von vordefinierten Konstanten enthalten kann, dann sollten Sie den Datentyp enumeration verwenden. Jeder enumeration-type hat seinen untergeordenten Datentyp (z.B. byte, short, integer oder long).

Beispiel: enum Variablenname {Menge};

enum Woche {Montag, Dienstag, Mittwoch, Donnerstag, Freitag, 
	Samstag, Sonntag};

Sie können natürlich auch in der Mengenangabe einen anderen Datentyp angeben:

Beispiel: enum Variablenname : Datentyp {Menge};

enum Woche : byte {Montag, Dienstag, Mittwoch, Donnerstag, Freitag, Samstag, Sonntag};

Reference Types

Ein reference-type kann eine Klasse, ein interface-type oder ein Array sein. Ein reference-type ist die Refernz zu einer Instanz, und damit letzlich zu einem Objekt. Der Wert null ist kompatibel mit allen Reference types und bedeutet die Nonexistenz einer Instanz.

Der reference-type gliedert sich in folgende Untertypen:

Class types

Der Class type definiert eine Datenstruktur welche Daten-Member (Konstanten, Felder und Events) und Funktions-Member (Methoden, Eigenschaften, Indexer, Operatoren, Konstruktoren und Destruktoren) beeinhaltet. Class types unterstützen Vererbung; das bedeutet, daß hergeleitete Classes die Base Class erweitern und spezialisieren können.

Delegate types

Ein delegate ist ein Referenztyp der sich auf eine Methode oder auf eine Objektinstanz und die Instanzmethode dieses Objektes bezieht. Der nächste Verwandte zum delegate in C oder C++ ist der Funktionspointer (addressof in VB), wobei ein Funktionspointer nur statische Funktionen referenziert, der delegate jedoch statische und Instanzmethoden. Der delegate speichert nicht nur den Methodenanfangspunkt sondern auch eine Referenz zum Instanzobjekt um die Methode aufzurufen.

Array types

Ein Array ist eine Datenstruktur welche eine Anzahl von Variablen beeinhaltet die durch berechnete Indizes zugänglich ist. Die Variablen die sich in einem Array befinden, werden auch als Elemente eines Arrays bezeichnet und sind alle vom selben Typ. Dieser Typ wird als "Elementtyp des Arrays" bezeichnet. Mehr Informationen zu Arrays erhalten Sie in einem unserer nächsten Artikel.

Object type

Der Object Type ist die ultimative Base class aller anderen Typen. Jeder Typ in C# läßt sich direkt oder indirekt vom Object Type herleiten. Das object Schlüsselwort ist einfach nur ein angenommener(anderer) Name für die vordefinierte System.Object Klasse. Das Keyword object ist genau das gleiche wie System.Object und umgekehrt.

String type

Der String type ist ein abgeschlossener Class type welcher direkt von Object abgeleitet ist. Instanzen der String Class repräsentieren Unicode Zeichenfolgen. Das string keyword ist einfach nur ein anderer Name für die vordefinierte System.String Class. Der Keyword string ist genau das selbe wie System.String und umgekehrt.

Interfaces

Ein Interface definiert einen Referenztyp der nur abstrakte Members (Mitglieder) hat. Ein interface wird dazu verwendet, um eine Schnittstellen-Vereinbarung zu schaffen. Eine Klasse oder ein struct, welches ein Interface implementiert, muß die Vereinbarung einhalten. Ein interface kann Methoden, Eigenschaften oder Indexer enthalten.

Boxing und Unboxing

Boxing und Unboxing ist ein zentraler Teil im Type-System von C# (und der Runtime). Es stellt ein Bindeglied zwischen value-types und reference-types zur Verfügung. Value-types haben den Vorteil, daß sie wenig Speicherplatz benötigen. In manchen Fällen ist es jedoch von Vorteil, daß value-types auch die die Eigenschaften von Objekten haben. Diese Übereinkunft macht den Hauptteil von C# aus, daß die Verknüpfung zwischen value-types und reference-types dadurch geschieht, daß ein value-type aus einem und in ein Objekt ungewandelt werden kann. Unter dem Motto "Es ist zwar alles ein Objekt, aber nur dann wenn es eines sein muß."

Boxing Vorgang

Der Boxing Vorgang beschreibt die Umwandlung von einem value-type zu einem Objekt. Bei dem Boxing Vorgang wird die Instanz eines Objekts erstellt und der ursprüngliche Wert des value-types wird in das neue Objekt kopiert.

Ein Beispiel:

...
int nVariable = 1; 
object oVariable = nVariable;
...

Hier geschieht folgendes: in der ersten Sourcecodezeile wird die Variable "nVariable" als integer Datentyp deklariert, und diese bekommt zusätzlich den Wert 1 zugewiesen. In der zweiten Zeile wird nun eine neue Instanz for das Objekt oVariable erstellt und ihr der Wert der Variable nVariable zugewiesen. Durch diesen Kopiervorgang erhalte ich 2 völlig unabhängige Variablen. Das heißt, wenn der Wert des Objekts oVariable geändert wird, dann hat sich der Wert von nVariable nicht ändert.

Die folgende kleine Anweisung beweist dies:

int nVariable = 1;
object oVariable = nVariable;
oVariable = 2;
Console.WriteLine("{0} {1}", nVariable, oVariable);

Die Werte, die ausgegeben werden sind einmal 1, und das zweite mal 2.

Unboxing Vorgang

Man könnte sagen, dies sei der umgekehrte Vorgang. Beim Unboxing Vorgang wird ein value type aus einem Objekt extrahiert. Der C# Compiler überprüft zusätzlich, ob die von Ihnen angeforderte Variable, welche Sie aus dem Objekt extrahieren wollen, tatsächlich den angeforderten unboxed Type entsprechen kann.

Ein Beispiel:

...
int nVariable = 1;
object oVariable = nVariable;
int nUBVariable = (int)oVariable;
...

Würde hier ein anderer Typ als int für die Unboxing Operation angefordert, bekäme man eine Exception.

Schlußbemerkung

Dies ist zugegebenermaßen eines der trocken Kapitel aus der C#-Programmierung. In diesem Artikel habe ich versucht Ihnen die verschieden Datentypen vorzustellen und das umcasten von Variablen zu Objekten (boxing) und umgekehrt (unboxing). Obwohl C# einige, für den Programmierer vereinfachende Funktionen und Dienstleistungen zur Verfügung stellt, ist der richtige Umgang mit Datentypen von grundlegender Bedeutung.

This printed page brought to you by AlphaSierraPapa

Verwandte Artikel

A Brief History of C#
http:/www.aspheute.com/artikel/20000713.htm
Deutsche Personalausweisnummern verifizieren
http:/www.aspheute.com/artikel/20020507.htm
Die Hashtable Klasse
http:/www.aspheute.com/artikel/20000823.htm
Enums lesbar machen
http:/www.aspheute.com/artikel/20010215.htm
Formularbasierte Authentifizierung in fünf Minuten
http:/www.aspheute.com/artikel/20020705.htm
Unions in C#
http:/www.aspheute.com/artikel/20020207.htm
Variable Parameterlisten in Funktionen
http:/www.aspheute.com/artikel/20020125.htm
Verwendung von Arrays in C#
http:/www.aspheute.com/artikel/20000731.htm
Web Services 101 in ASP.NET
http:/www.aspheute.com/artikel/20010621.htm
Web.Config 101
http:/www.aspheute.com/artikel/20010802.htm
Wochenberechnung mit .NET
http:/www.aspheute.com/artikel/20020905.htm

 

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.