Kolumne: C# im Fokus

Funktion und Verwendung von dynamic
Kommentare

Das mit .NET 4.0 eingeführte Schlüsselwort dynamic, das die standardmäßig durchgeführte Typprüfung durch den Compiler umgeht, steht in dieser Ausgabe im Mittelpunkt der C#-Kolumne. Aber wann und wieso soll das hilfreich sein?

Die erste Version der Programmiersprache C# war durchgängig statisch typisiert, d. h., zur Kompilierzeit prüft der Compiler die gültige Verwendung von Variablentypen (Listing 1). Die Methode A in Listing 1 erwartet als Parameter einen Datentyp vom Typ string. Bei dem konkreten Aufruf der Methode im Hauptprogramm wird allerdings ein int-Datentyp übergeben. Dieser Versuch führt unweigerlich zu der Compiler-Fehlermeldung Argument 1: cannot convert from“‚int“ to „string“‚ während der Kompilierung. Dadurch kann das Programm nicht ausgeführt werden.

Listing 1

public static void A(string input) {  }
static void Main(string[] args)
{
  A(5); 
  ...
}  

C# – Statisch und typisiert

Eine statisch typisierte Programmiersprache wie C# zeichnet sich durch die Typprüfung während der Kompilierzeit aus. Diese Eigenschaft hilft Fehler zu vermeiden, die ansonsten erst zur Laufzeit auftreten würden. Durch die frühzeitige Fehlererkennung wird die Stabilität der Anwendung verbessert. Da jede Variable bei der Anlage typisiert werden muss, wird der entstehende Quellcode lesbarer und wartungsfreundlicher. Zudem kann ein stark typisiertes Programm unter Umständen eine bessere Performance erzielen als ein nichttypisiertes Programm, da bei einer starken Typisierung teilweise auf Typkonvertierungen zur Laufzeit verzichtet werden kann. Auch Entwicklungsumgebungen wie Microsoft Visual Studio profitieren von einer starken Typisierung und ermöglichen so IntelliSense.

C# – Dynamisch?

Mit dem Einzug des Schlüsselwortes dynamic in .NET 4.0 führt C# einen Mechanismus ein, der bisher dynamischen Programmiersprachen wie z. B. JavaScript, Lisp Groovy usw. vorbehalten war. Bei dynamischen Programmiersprachen findet eine Typprüfung erst zur Laufzeit statt, d. h. eventuelle Typunverträglichkeiten werden erst bei der Programmausführung erkannt und führen in der Regel zu einem Programmabbruch. Das liegt daran, dass bei dynamischen Sprachen die Bindung an einen Typ erst zu Laufzeit stattfindet (Late Binding). Das dynamic-Schlüsselwort ermöglicht nun auch in C# eine späte Bindung einer Variable an einen bestimmten Typ.

object vs. dynamic

Seit der ersten Version von C# existiert der Datentyp object, der zur Speicherung jeglicher Daten verwendet werden kann. Daher verhält sich object zunächst wie dynamic. Jedoch unterscheiden sich die beiden Schlüsselwörter gravierend, wie Listing 2 demonstriert. Der wesentliche Unterschied besteht in der automatischen Typerkennung. Im vorliegenden Beispiel wird der Variablen dyn1, die vom Typ dynamic ist, der Zahlenwert 10 zugewiesen. Einer zweiten Variablen obj1, diesmal vom Typ object, wird der gleiche Zahlenwert zugewiesen. Anschließend wird der Wert 10 auf beide Variablen mittels +-Operator addiert.

Wie in Listing 2 erkennbar ist, muss die object-basierte Variable explizit zu einem Ganzzahlendatentyp konvertiert werden, ansonsten moniert der Compiler schon im Vorfeld die Typenunverträglichkeit. Die darauf folgenden vier Codezeilen verdeutlichen das Verhalten von dynamic beim Einsatz als Parametertyp einer Methode. Die Methode A erwartet einen Parameter, addiert auf diesen den Wert 10 und gibt ihn als int-Datentyp zurück. Die ersten beiden Aufrufe (1) und (2) in Listing 2 verlaufen ohne Probleme, die Aufrufe (3) und (4) verursachen jedoch einen Laufzeitfehler. Der übergebene Wert, in diesem Fall eine Zeichenkette mit dem Inhalt 10, kann zwar übergeben werden, jedoch scheitert die implizite Konvertierung in einen Ganzzahlentyp.

Dieses Beispiel zeigt eine wesentliche Eigenschaft dynamischer Sprachen: Der Datentyp einer Variablen wird nicht durch eine explizite Typangabe festgelegt, sondern der Inhalt der Variablen repräsentiert den Typ. Das heißt, eine als object definierte Variable bleibt so lange vom Typ object, bis eine Typkonvertierung in einen anderen (kompatiblen) Typ durchgeführt wurde.

Listing 2

public static void Example1()
{
  object obj1 = 10;
  object obj2 = "10";
  dynamic dyn1 = 10;
  dynamic dyn2 = "10";
  dyn1 = dyn1 + 10;  // Keine Konvertierung
  obj1 = (int)obj1 + 10;  // Konvertierung notwendig
  Console.WriteLine(MethodA(obj1)); // (1)
  Console.WriteLine(MethodA(dyn1)); // (2)
  Console.WriteLine(MethodA(obj2)); // (3) Laufzeitfehler 
  Console.WriteLine(MethodA(dyn2)); // (4) Laufzeitfehler 
}
public static int MethodA(dynamic param)
{
  return param + 10;
}  

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -