Kapitel 17 Arrays
Arrays sind in C# Verweisobjekte, die außerhalb
des Heaps und nicht dem Stack zugeordnet werden. Die Speicherung
der Elemente eines Arrays richtet sich nach dem Elementtyp. Wenn der
Elementtyp ein Verweistyp ist (z. B. string), speichert
das Array Verweise auf Zeichenfolgen. Handelt es sich bei den Elementen
um Wertetypen (beispielsweise numerische Typen oder struct-Typen),
werden die Elemente direkt im Array gespeichert. Mit anderen Worten,
ein Array aus Wertetypen enthält keine Instanzen, für die
ein Boxing durchgeführt wurde.
Arrays werden mit Hilfe der folgenden Syntax deklariert:
<type>[] identifier;
Der anfängliche Wert eines Arrays ist null.
Ein Arrayobjekt wird mit Hilfe von new erstellt:
int[] store = new int[50];
string[] names = new string[50];
Bei der Erstellung eines Arrays enthält dieses
anfänglich die Standardwerte für die Typen im Array. Für
das store-Array handelt es sich bei den Elementen um ein
int mit dem Wert 0. Für das names-Array
liegen string-Elemente mit dem Wert null vor.
17.1 Arrayinitialisierung
 
Arrays können während der Erstellung initialisiert
werden. Bei der Initialisierung kann das Element new int[x]
weggelassen werden; der Compiler ermittelt dann die Größe
des zuzuordnenden Arrays anhand der Anzahl der Elemente in der Initialisierungsliste:
int[] store = {0, 1, 2, 3, 10, 12};
Die vorstehende Zeile ist gleichwertig mit der folgenden:
int[] store = new int[6] {0, 1, 2, 3, 10, 12};
17.2 Mehrdimensionale und unregelmäßige
Arrays
 
Zur Indizierung von mehrdimensionalen Elementen kann entweder ein
mehrdimensionales oder ein unregelmäßiges (jagged) Array verwendet
werden.
17.2.1 Mehrdimensionale Arrays
 
Mehrdimensionale Arrays verfügen über
mehr als eine Dimension.
int[,] matrix = new int[5, 2];
matrix[0, 0] = 5;
matrix[5, 5] = 10;
Beim matrix-Array lautet der Wert für
die erste Dimension 5 und für die zweite Dimension 2.
Dieses Array könnte anhand folgender Anweisung initialisiert werden:
int[,] matrix = {{1, 1}, {2, 2}, {3, 5}, {4, 5}};
Der Wert für die erste Dimension des matrix-Arrays
lautet 4, der für die zweite Dimension 2.
Mehrdimensionale Arrays werden gelegentlich auch
als rechteckige Arrays bezeichnet, da die Elemente in eine rechteckige
Tabelle geschrieben werden können (für Dimensionen <= 2).
Wenn die Matrize zugeordnet wird, wird ein einzelner Chunk vom Heap
zur Speicherung des gesamten Arrays verwendet. Dies wird in Abbildung 17.1
veranschaulicht.
Abbildung 17.1 Speicherung in einem
mehrdimensionalen Array
|
17.2.2 Unregelmäßige Arrays
 
Ein unregelmäßiges Array ist lediglich
ein Array von Arrays und wird als »unregelmäßig«
(jagged) bezeichnet, da es nicht zwangsläufig rechteckig
ist. Beispiel:
int[][] matrix = new int[3][];
matrix[0] = new int[10];
matrix[1] = new int[11];
matrix[2] = new int[2];
matrix[0][3] = 4;
matrix[1][1] = 8;
matrix[2][0] = 5;
Das matrix-Array weist hier nur eine
Dimension mit 3 Elementen auf. Bei den Elementen handelt es sich
um integer-Arrays. Das erste Element ist ein Array von 10 integer-Werten,
das zweite Array umfasst 11 integer-Werte, das dritte
Array setzt sich aus 2 integer-Werten zusammen.
Da es sich bei den Elementen eines unregelmäßigen
Arrays um Arrays handelt, werden bei der Zuordnung des Arrays oberster
Ebene alle Elemente mit dem Wert null initialisiert. Daher
muss jedes Element als gültiges Array initialisiert werden. Aufgrund
dieser Tatsache gibt es keine Initialisierungssyntax für die Elemente eines unregelmäßigen
Arrays. Bei zweidimensionalen Arrays kann der Code jedoch folgendermaßen
umgeschrieben werden:
int[][] matrix = {new int[5], new int[4], new int[2]};
matrix[0][3] = 4;
matrix[1][1] = 8;
matrix[2][0] = 5;
Dieses Array wird in Abbildung 17.2 dargestellt.
Die matrix-Variable ist ein Verweis auf ein Array, das
drei Verweise auf integer-Arrays umfasst. Für dieses
Array sind vier Heapzuordnungen erforderlich.
Abbildung 17.2 Speicherung in einem
unregelmäßigen Array
|
17.3 Arrays vom Verweistyp
 
Arrays vom Verweistyp können etwas verwirrend
wirken, da die Elemente des Arrays mit null, nicht mit
dem Elementtyp initialisiert werden. Beispiel:
class Employee
{
public void LoadFromDatabase(int employeeID)
{
// hier Code laden
}
}
class Test
{
public static void Main()
{
Employee[] emps = new Employee[3];
emps[0].LoadFromDatabase(15);
emps[1].LoadFromDatabase(35);
emps[2].LoadFromDatabase(255);
}
}
Beim Aufruf von LoadFromDatabase()
wird eine Nullausnahme erzeugt, da die referenzierten Elemente nicht gesetzt
wurden und daher immer noch den Wert null aufweisen.
Die Klasse kann folgendermaßen umgeschrieben
werden:
class Employee
{
public static Employee LoadFromDatabase(int employeeID)
{
Employee emp = new Employee();
// hier Code laden
return(emp);
}
}
class Test
{
public static void Main()
{
Employee[] emps = new Employee[3];
emps[0] = Employee.LoadFromDatabase(15);
emps[1] = Employee.LoadFromDatabase(35);
emps[2] = Employee.LoadFromDatabase(255);
}
}
So ist es möglich, eine Instanz zu erstellen,
diese zu laden und im Array zu speichern.
Arrays werden aus Leistungsgründen nicht initialisiert.
Wenn der Compiler die Initialisierung übernähme, müsste
die gleiche Initialisierung für jedes einzelne Element vorgenommen
werden. Handelt es sich hierbei nicht um die richtige Initialisierung,
sind sämtliche Zuordnungen vergeudet.
17.4 Arraykonvertierungen
 
Konvertierungen zwischen Arrays sind, basierend
auf der Dimensionenanzahl und den verfügbaren Konvertierungen, zwischen
den Elementtypen möglich.
Eine implizite Konvertierung von Array S
in Array T ist möglich, wenn die Arrays die gleiche
Anzahl Dimensionen aufweisen, wenn die Elemente von S
eine implizite Verweiskonvertierung in den Elementtyp von T zulassen
und es sich sowohl bei S als auch bei T
um Verweistypen handelt. Mit anderen Worten, wenn ein Array aus Klassenverweisen
vorliegt, kann dieses in ein Array des Basistyps der Klasse konvertiert
werden.
Explizite Konvertierungen weisen die gleichen Anforderungen
auf, abgesehen davon, dass eine explizite Konvertierung der Elemente
von S in den Elementtyp von T möglich
sein muss.
using System;
class Test
{
public static void PrintArray(object[] arr)
{
foreach (object obj in arr)
Console.WriteLine("Word: {0}", obj);
}
public static void Main()
{
string s = "I will not buy this record, it is scratched.";
char[] separators = {' '};
string[] words = s.Split(separators);
PrintArray(words);
}
}
In diesem Beispiel kann das aus Worten bestehende
string-Array als object-Array übergeben
werden, da jedes string-Element in ein object
konvertiert werden kann.
17.5 System.Array-Typ
 
Da die Arrays in C# auf dem .NET-Laufzeitumgebungstyp
System.Array basieren, können verschiedene Operationen
ausgeführt werden, die herkömmlicherweise nicht von Arraytypen
unterstützt werden.
17.5.1 Sortieren und Suchen
 
Der System.Array-Typ verfügt über
integrierte Funktionen zum Sortieren und Suchen. Die Sort()-Funktion
übernimmt die Sortierung von Arrayelementen, die Funktionen IndexOf(), LastIndexOf()
und BinarySearch() können zum Suchen von Elementen
im Array eingesetzt werden.
Diese Funktionen können für die integrierten
Typen eingesetzt werden. Informationen zur Aktivierung dieser Funktionen
für benutzerdefinierte Klassen oder Strukturen finden Sie in Kapitel 27,
Freunde finden mit den .NET-Frameworks.
17.5.2 Reverse
 
Das Aufrufen von Reverse() führt
zu einer Umkehrung aller Elemente im Array.
using System;
class Test
{
public static void Main()
{
int[] arr = {5, 6, 7};
Array.Reverse(arr);
foreach (int value in arr)
{
Console.WriteLine("Value: {0}", value);
}
}
}
Dieser Code erzeugt die folgende Ausgabe:
7
6
5
|