Dynamisches .NET

Erläuterungen zum Schlüsselwort "dynamic" in C# 4

Alexandra Rusina

Das dynamic-Schlüsselwort und die Dynamic Language Runtime (DLR) sind wesentliche neue Funktionen von C# 4 und Microsoft .NET Framework 4 und riefen bei ihrer Ankündigung großes Interesse hervor. Damit einher gingen jedoch auch viele Fragen. Es gab auch eine Reihe von Antworten. Diese sind jedoch über verschiedene Dokumentationen, technische Blogs und Artikel verstreut. Daher werden in Foren und auf Konferenzen immer wieder die gleichen Fragen gestellt.

In diesem Artikel erhalten Sie eine allgemeine Übersicht über die neuen dynamic-Funktionen in C# 4 und detaillierte Informationen über deren Kompatibilität mit anderen Sprach- und Frameworkfunktionen, wie Reflektion und implizit typisierte Variablen. Da viele Informationen bereits verfügbar sind, verwende ich gelegentlich klassische Beispiele und gebe die Links zu den entsprechenden Quellen an. Ich stelle Ihnen auch zahlreiche Links zu weiteren Artikeln mit Informationen bereit.

Was wird unter "dynamisch" verstanden?

Programmiersprachen werden manchmal in statisch typisierte und dynamisch typisierte Sprachen unterteilt. C# und Java werden häufig als statisch typisierte Sprachen betrachtet, während Python, Ruby und JavaScript als Beispiele für dynamisch typisierte Sprachen gelten.

Grundsätzlich gesagt, führen dynamische Sprachen keine Typenprüfungen zur Kompilierzeit aus und identifizieren den Objekttyp erst zur Laufzeit. Dies hat Vor- und Nachteile: Häufig ist der Code einfacher und kann schneller erstellt werden. Gleichzeitig jedoch erhalten Sie keine Compilerfehler und müssen Einheiten testen oder andere Verfahren anwenden, um das korrekte Verhalten einer Anwendung sicherzustellen.

Ursprünglich wurde C# als rein statische Sprache entwickelt. In C# 4 wurden jedoch dynamische Elemente hinzugefügt, um die Interoperabilität mit dynamischen Sprachen und Frameworks zu verbessern. Das C#-Team betrachtete mehrere Entwurfsoptionen, entschied sich schließlich jedoch für die Hinzufügung eines neuen Schlüsselworts, um diese Funktionen zu unterstützen: dynamic.

Das dynamic-Schlüsselwort dient als statische Typendeklaration im C#-Typensystem. Auf diese Weise stehen C# die dynamischen Funktionen bereit, und es bleibt dennoch eine statisch typisierte Sprache. Warum und wie diese Entscheidung getroffen wurde, wird in der Präsentation "Dynamische Bindung in C# 4" von Mads Torgersen in PDC09 (microsoftpdc.com/2009/FT31) erklärt (möglicherweise in englischer Sprache). Neben anderen Entscheidungen wurde auch die Entscheidung getroffen, dass dynamische Objekte integrale Bestandteile von C# sind, sodass die dynamischen Funktionen nicht aktiviert oder deaktiviert werden können. Es wurde keine der Visual Basic-Option "Strict On/Off" vergleichbare Option hinzugefügt.

Wenn Sie das dynamic-Keyword verwenden, teilen Sie dem Compiler mit, die Prüfung zur Kompilierzeit zu deaktivieren. Es gibt zahlreiche Beispiele für die Verwendung dieses Schlüsselworts im Web und in der MSDN-Dokumentation (msdn.microsoft.com/library/dd264736). Ein häufig verwendetes Beispiel ist das folgende:

dynamic d = "test";
Console.WriteLine(d.GetType());
// Prints "System.String".

d = 100;
Console.WriteLine(d.GetType());
// Prints "System.Int32".

Wie Sie sehen können, ist es möglich, einer als dynamisch deklarierten Variablen Objekte verschiedenen Typs zuzuweisen. Der Code wird kompiliert, und der Typ des Objekts wird zur Laufzeit identifiziert. Der folgende Code wird ebenfalls kompiliert, löst jedoch zur Laufzeit eine Ausnahme aus:

dynamic d = "test";

// The following line throws an exception at run time.
d++;

Der Grund ist der gleiche: Der Compiler kennt den Laufzeittyp des Objekts nicht und kann Ihnen daher nicht sagen, dass die Inkrementierungsoption in diesem Fall nicht unterstützt wird.

Das Fehlen der Typprüfung zur Kompilierzeit führt zum Fehlen von IntelliSense. Da der C#-Compiler den Typ des Objekts nicht kennt, kann er dessen Eigenschaften und Methoden nicht enumerieren. Dieses Problem kann mittels eines zusätzlichen Typrückschlusses gelöst werden, wie in den IronPython-Tools für for Visual Studio. C# stellt dies zurzeit nicht bereit.

In vielen Szenarien, die von den dynamischen Funktionen profitieren könnten, war IntelliSense jedoch von vornherein nicht verfügbar, da der Code Zeichenfolgenliterale verwendete. Dieses Problem wird in diesem Artikel an späterer Stelle ausführlicher behandelt.

"dynamic", "object" oder "var"?

Wie unterscheiden sich dynamic, object und var, und wie sollten Sie diese Schlüsselwörter verwenden? Im Folgenden finden Sie kurze Definitionen dieser Schlüsselwörter und einige Beispiele.

Das object-Schlüsselwort stellt den System.Object-Typ dar. Dies ist der Stammtyp in der C#-Klassenhierarchie. Dieses Schlüsselwort wird häufig verwendet, wenn es keine Möglichkeit zur Identifizierung des Objekttyps zur Laufzeit gibt. Dies ist in verschiedenen Interoperabilitätsszenarien häufig der Fall.

Sie müssen explizite Umwandlungen verwenden, um eine Variable zu deklarieren, die als Objekt für einen bestimmten Typ deklariert wurde.

object objExample = 10;
Console.WriteLine(objExample.GetType());

Dies druckt offensichtlich System.Int32. Der statische Typ ist jedoch System.Object. Daher benötigen Sie hier eine explizite Umwandlung:

objExample = (int)objExample + 10;

Sie können Werte verschiedener Typen zuweisen, da sie alle von System.Object erben:

objExample = "test";

Das var-Schlüsselwort wird seit C# 3.0 für implizit typisierte lokale Variablen und anonyme Typen verwendet. Dieses Schlüsselwort wird häufig mit LINQ verwendet. Wenn eine Variable mittels des var-Schlüsselworts deklariert wird, wird der Variablentyp von der Initialisierungszeichenfolge zur Kompilierzeit abgeleitet. Der Typ der Variablen kann zur Laufzeit nicht geändert werden. Wenn der Compiler den Typ nicht ableiten kann, tritt ein Compilationsfehler auf:

var varExample = 10;
Console.WriteLine(varExample.GetType());

Dies druckt System.Int32, und es ist das gleiche wie der statische Typ.

Im folgenden Beispiel ist keine Umwandlung erforderlich, da die statische Typisierung von varExample System.Int32 ist:

varExample = varExample + 10;

Diese Zeile wird nicht kompiliert, da Sie varExample nur ganze Zahlen zuweisen können.:

varExample = "test";

Das dynamic-Schlüsselwort, das in C# 4 eingeführt wurde, vereinfacht das Schreiben und die Pflege bestimmter Szenarien, die traditionell das object-Schlüsselwort verwendet haben. Tatsächlich verwendet der dynamic-Typ den System.Object-Typ. Anders als das object.Schlüsselwort erfordert er jedoch keine expliziten Umwandlungsprozesse zur Kompilierzeit, da es den Typ nur zur Laufzeit identifiziert:

dynamic dynamicExample = 10;
Console.WriteLine(dynamicExample.GetType());

Dies druckt System.Int32.

In der folgenden Zeile ist keine Umwandlung erforderlich, da der Typ nur zur Laufzeit identifiziert wird:

dynamicExample = dynamicExample + 10;

Sie können dynamicExample Werte verschiedener Typen zuweisen:

dynamicExample = "test";

Es gibt einen detaillierten Blogeintrag über die Unterschiede zwischen den Schlüsselwörtern object und dynamic im C# FAQ-Blog (bit.ly/c95hpl, möglicherweise in englischer Sprache).

Was manchmal zu Verwirrung führt, ist die Tatsache, dass alle diese Schlüsselwörter zusammen verwendet werden können. Sie schließen sich nicht gegenseitig aus. Betrachten wir beispielsweise den folgenden Code:

dynamic dynamicObject = new Object();
var anotherObject = dynamicObject;

Was ist der Typ von anotherObject? Die Antwort lautet: dynamic. Denken Sie daran, dass dynamic im C#-Typensystem tatsächlich ein statischer Typ ist, sodass der Compiler diesen Typ für das anotherObject ableitet. Es ist wichtig zu verstehen, dass das var-Schlüsselwort nur eine Anweisung für den Compiler darstellt, den Typ aus dem Initialisierungsausdruck der Variablen abzuleiten. var selbst ist kein Typ.

Die Dynamic Language Runtime

Wenn Sie das Wort "dynamic" im Zusammenhang mit C# hören, bezieht es sich in der Regel auf eines der beiden folgenden Konzepte: das dynamic-Schlüsselwort in C# 4 oder die DLR. Obwohl diese beiden Konzepte miteinander verwandt sind, ist es wichtig, auch den Unterschied zu verstehen.

Die DLR dient zwei Hauptzielen. Als Erstes ermöglicht sie die Zusammenarbeit zwischen dynamischen Sprachen und dem .NET Framework. Als Zweites verleiht sie C# und Visual Basic ein dynamisches Verhalten.

Die DLR wurde auf der Basis von Erfahrungen bei der Entwicklung von IronPython (ironpython.net) entwickelt. Dies war die erste dynamische Sprache, die im .NET Framework implementiert wurde. Bei der Arbeit an IronPython stellte das Team fest, dass sie die Implementierung für mehr als eine Sprache verwenden konnten. Daher entwickelten sie eine gemeinsame zugrunde liegende Plattform für dynamische .NET-Sprachen. Wie IronPython wurde auch die DLR zu einem Open-Source-Projekt, und der Quellcode ist nun unter dlr.codeplex.com verfügbar.

Später wurde die DLR auch in .NET Framework 4 integriert, um dynamische Funktionen in C# und Visual Basic zu unterstützen. Wenn Sie nur das dynamic-Schlüsselwort in C# 4 verwenden müssen, können Sie einfach das .NET Framework verwenden, und in den meisten Fällen behandelt es selbstständig alle Interaktionen mit der DLR. Wenn Sie jedoch eine neue dynamische Sprache in .NET implementieren oder zu .NET portieren möchten, können Sie möglicherweise von den zusätzlichen Helper-Klassen im Open-Source-Projekt profitieren. Dieses verfügt über mehr Funktionen und Dienste für die Sprachimplementierung.

Verwenden von dynamic in einer statisch typisierten Sprache

Es wird nicht erwartet, dass jeder Programmierer dynamic anstelle der statischen Typendeklarationen verwendet, wann immer möglich. Die Prüfung zur Kompilierzeit ist ein leistungsfähiges Mittel, und je mehr Sie von ihr profitieren können, desto besser. Noch einmal, dynamische Objekte in C# unterstützen IntelliSense nicht. Dies kann sich auf die Gesamtproduktivität auswirken.

Gleichzeitig gibt es jedoch Szenarien, die nur schwer in C# implementiert werden konnten, bevor es das dynamic-Schlüsselwort und die DLR gab. In den meisten Fällen wurden ohnehin der System.Object-Typ und die explizite Umwandlung verwendet, sodass nicht viele Vorteile durch die Prüfung zur Kompilierzeit und IntelliSense erzielt wurden. Dazu einige Beispiele:

Das bekannteste Szenario besteht darin, dass Sie das object-Schlüsselwort für die Interoperabilität mit anderen Sprachen oder Frameworks verwenden müssen. In der Regel müssen Sie sich auf die Reflektion verlassen, um den Typ des Objekts abzurufen und auf dessen Eigenschaften und Methoden zuzugreifen. Die Syntax ist manchmal schwer zu verstehen, weswegen der Code nur schwer gepflegt werden kann. Die Verwendung von dynamic kann in diesen Fällen einfacher und komfortabler als die Reflektion sein.

Anders Hejlsberg hat hierzu ein sehr gutes Beispiel unter PDC08 (channel9.msdn.com/pdc2008/TL16), das folgendermaßen aussieht:

object calc = GetCalculator();
Type calcType = calc.GetType();
object res = calcType.InvokeMember(
  "Add", BindingFlags.InvokeMethod, 
  null, new object[] { 10, 20 });
int sum = Convert.ToInt32(res);

Die Funktion gibt einen Rechner zurück. Das System erkennt jedoch den exakten Typ des Rechnerobjekts zur Kompilierzeit nicht. Der Code verlässt sich ausschließlich darauf, dass dieses Objekt über die Add-Methode verfügen sollte. Beachten Sie, dass Sie IntelliSense für diese Methode nicht erhalten, da Sie den Namen als Zeichenfolgeliteral bereitstellen.

Bei Verwendung des dynamic-Schlüsselworts sieht der Code so einfach wie der folgende aus:

dynamic calc = GetCalculator();
int sum = calc.Add(10, 20);

Die Annahmen sind die gleichen: Es gibt ein Objekt mit einem unbekannten Typ, für das wir die Add-Methode erwarten. Wie im vorherigen Beispiel erhalten Sie IntelliSense für diese Methode nicht. Die Syntax ist jedoch wesentlich einfacher zu verstehen. Sie ist dem Aufruf einer typischen .NET-Methode vergleichbar.

Dynamische Methodenbehälter

Ein weiteres Beispiel, in denen dynamic helfen kann, besteht in der Erstellung dynamischer Methodenbehälter, bei denen es sich um Objekte handelt, die Eigenschaften und Methoden zur Laufzeit hinzufügen und entfernen können.

Das .NET Framework 4 hat einen neuen Namespace: System.Dynamic. Der Namespace ist tatsächlich Bestandteil der DLR. Die System.Dynamic.ExpandoObject- und System.Expando.DynamicObject-Klassen können Ihnen in Verbindung mit dem neuen dynamic-Schlüsselwort helfen, dynamische Strukturen und Hierarchien auf eine klare und leicht verständliche Art zu erstellen.

Im Folgenden finden Sie ein Beispiel dafür, wie Sie eine Eigenschaft und eine Methode durch Verwendung der ExpandoObject-Klasse hinzufügen können:

dynamic expando = new ExpandoObject();
expando.SampleProperty = 
  "This property was added at run time";
expando.SampleMethod = (Action)(
  () => Console.WriteLine(expando.SampleProperty));
expando.SampleMethod();

Bei anspruchsvolleren Szenarien sollten Sie sich in der MSDN-Dokumentation für die ExpandoObject- und DynamicObject-Klassen informieren. Sie sollten auch die Artikel "Dynamische Methodenbehälter" von Bill Wagner (msdn.microsoft.com/library/ee658247) und "Dynamic in C# 4.0: Einführung von ExpandoObject" im C# FAQ-Blog (bit.ly/amRYRw) lesen (beide möglicherweise in englischer Sprache).

Wrapperklassen

Sie können Ihrer eigenen Bibliothek eine bessere Syntax bereitstellen oder einen Wrapper für eine vorhandene Bibliothek erstellen. Dies ist im Vergleich zu den vorherigen beiden Szenarien ein anspruchsvolleres Szenario und erfordert ein tieferes Verständnis der DLR.

In einfachen Fällen können Sie die DynamicObject-Klasse verwenden. In dieser Klasse können Sie die statische Deklaration von Methoden und Eigenschaften mit dem dynamischen Verteiler mischen. So können Sie ein Objekt speichern, für das Sie in einer Klasseneigenschaft eine bessere Syntax bereitstellen möchten. Gleichzeitig können Sie alle Prozesse, die dieses Objekt betreffen, mittels eines dynamischen Verteilers behandeln.

Betrachten Sie zum Beispiel die DynamicString-Klasse in Abbildung 1, die eine Zeichenfolge umschließt und die Namen aller Methoden anzeigt, bevor diese Methoden mittels Reflektion aufgerufen werden.

Abbildung 1 DynamicString

public class DynamicString : DynamicObject {
  string str;

  public DynamicString(string str) {
    this.str = str;
  }

  public override bool TryInvokeMember(
    InvokeMemberBinder binder, object[] args, 
    out object result) {

    Console.WriteLine("Calling method: {0}", binder.Name);

    try {
      result = typeof(string).InvokeMember(
        binder.Name,
        BindingFlags.InvokeMethod |
        BindingFlags.Public |
        BindingFlags.Instance,
        null, str, args);
      return true;
    }
    catch {
      result = null;
      return false;
    }
  }
}

Um diese Klasse zu instanziieren, sollten Sie das dynamic-Schlüsselwort verwenden:

dynamic dStr = new DynamicString("Test");
Console.WriteLine(dStr.ToUpper()); 
Console.ReadLine();

Natürlich ist dieses Beispiel nicht wirklich realistisch und effizient. Wenn Sie jedoch über eine API verfügen, die bereits stark von Reflektion abhängig ist, können Sie alle Aufrufe mittels Reflektion umschließen, wie hier gezeigt, sodass diese für die Endbenutzer Ihrer API nicht angezeigt werden.

Weitere Beispiele finden Sie in der MSDN-Dokumentation (msdn.microsoft.com/library/system.dynamic.dynamicobject) und im Blogeintrag "Dynamic in C# 4.0: Erstellen von Wrappern mit DynamicObject" im C# FAQ-Blog (bit.ly/dgS3od), beides möglicherweise in englischer Sprache.

Wie bereits erwähnt, wird die DynamicObject-Klasse von der DLR bereitgestellt. Sie benötigen nur DynamicObject oder ExpandoObject, um ein dynamischen Objekt zu generieren. Einige dynamische Objekte verfügen jedoch über eine komplizierte Bindungslogik für den Zugriff auf Mitglieder oder aufrufende Methoden. Diese Objekte müssen die IDynamicMetaObjectProvider-Schnittstelle implementieren und einen eigenen dynamischen Verteiler bereitstellen. Dies ist ein anspruchsvolles Szenario. Wenn Sie sich hierfür interessieren, können Sie mehr dazu in den folgenden beiden Artikeln erfahren: "Implementieren dynamischer Schnittstellen" von Bill Wagner (msdn.microsoft.com/vcsharp/ff800651) und "Erste Schritte mit der DLR als ein Bibliotheksautor" von Alex Turner und Bill Chiles (dlr.codeplex.com), beide möglicherweise in englischer Sprache.

Skriptfähige Anwendungen

Skripte sind eine gute Möglichkeit, Anwendungen Erweiterbarkeit bereitzustellen. Microsoft Office kann hier als gutes Beispiel dienen: Aufgrund von Visual Basic for Applications (VBA) sind zahlreiche Makros, Add-Ons und Plug-Ins vorhanden. Nun ermöglicht Ihnen die DLR die Erstellung skriptfähiger Anwendungen, da sie einen allgemeinen Satz von Hosting-APIs für Sprachen bereitstellt.

Sie können zum Beispiel eine Anwendung erstellen, in der die Benutzer Funktionen selbst hinzufügen können, ohne dass sie auf neue Funktionen des Hauptprodukts warten müssen. Sie können einem Spiel neue Zeichnungen und Karten oder einer Geschäftsanwendung neue Graphen hinzufügen.

Sie müssen die Open-Source-Version der DLR auf dlr.codeplex.com verwenden und nicht die Version, die von .NET Framework 4 bereitgestellt wird, da das Skripten und Hosten von APIs in der DLR zurzeit nur von der Open-Source-Version unterstützt wird. Eine weitere Annahme ist, dass Sie die Skripts nicht mit C#, sondern mit einer der dynamischen .NET-Sprachen wie IronPython oder IronRuby erstellen. Alle Sprachen können diese APIs jedoch unterstützen, sogar solche, die nicht auf der DLR implementiert sind.

Details zu dieser Funktionalität finden Sie in der Präsentation "Verwenden dynamischer Sprachen für die Entwicklung skriptfähiger Anwendungen" von Dino Viehland auf PDC09 (microsoftpdc.com/2009/FT30, möglicherweise in englischer Sprache).

Identifizieren dynamischer Objekte

Wie können Sie dynamische Objekte von anderen Objekten unterscheiden? Eine einfache Möglichkeit besteht in der Verwendung integrierter IDE-Funktionen. Sie können mit dem Mauszeiger auf das Objekt zeigen, um dessen Deklarationstyp anzuzeigen, oder die Verfügbarkeit von IntelliSense überprüfen (siehe Abbildung 2).

image: Dynamic Object in Visual Studio

Abbildung 2Dynamisches Objekt in Visual Studio

Zur Laufzeit werden die Dinge jedoch komplizierter. Sie können nicht überprüfen, ob die Variable durch das dynamic-Schlüsselwort deklariert wurde, da der Laufzeittyp des dynamischen Objekts der Typ des Werts ist, den es speichert, und Sie können die statische Typdeklaration nicht abrufen. Es ist der gleiche Fall wie die Deklaration der Variablen als Objekt. Zur Laufzeit können Sie nur den Typ des Werts erhalten, den die Variable speichert. Sie können nicht erkennen, ob diese Variable ursprünglich als Objekt deklariert wurde.

Sie können jedoch zur Laufzeit erkennen, ob ein Objekt aus der DLR stammt. Dies kann wichtig sein, da Objekte von Typen wie ExpandoObject und DynamicObject ihr Verhalten zur Laufzeit ändern können. Sie können zum Beispiel Eigenschaften und Methoden hinzufügen und löschen.

Sie können auch keine voreingestellten Reflektionsmethoden verwenden, um Informationen zu solchen Objekten abzurufen. Wenn Sie einer Instanz der ExpandoObject-Klasse eine Eigenschaft hinzufügen, können Sie diese Eigenschaften nicht aus der Reflektion erhalten.

dynamic expando = new ExpandoObject();
expando.SampleProperty = "This property was added at run time";
PropertyInfo dynamicProperty = 
  expando.GetType().GetProperty("SampleProperty");
// dynamicProperty is null.

Das Gute ist, dass in .NET Framework 4 alle Objekte, die Mitglieder dynamisch hinzufügen und entfernen können, eine bestimmte Schnittstelle implementieren müssen: System.Dynamic.IDynamicMetaObjectProvider. Sowohl die DynamicObject- als auch die ExpandoObject-Klasse implementieren diese Schnittstelle. Dies bedeutet jedoch nicht, dass jedes Objekt, das mittels des dynamic-Schlüsselworts deklariert wird, diese Schnittstelle implementiert:

dynamic expando = new ExpandoObject();
Console.WriteLine(expando is IDynamicMetaObjectProvider);
// True

dynamic test = "test";
Console.WriteLine(test is IDynamicMetaObjectProvider);
// False

Wenn Sie daher das dynamic-Schlüsselwort zusammen mit Reflektion verwenden, müssen Sie beachten, dass Reflektion nicht für dynamisch hinzugefügte Eigenschaften und Methoden funktioniert. Es ist daher möglicherweise eine gute Idee, zu prüfen, ob das Objekt, auf das Sie reflektieren, die IDynamicMetaObjectProvider-Schnittstelle implementiert.

Interoperabilität von dynamic und COM

Das COM-Interoperabilitätsszenario, das durch das C#-Team mit der Veröffentlichung von C# 4 schwerpunktmäßig angestrebt wurde, bestand in der Programmierung für Microsoft Office-Anwendungen wie Word und Excel. Diese Aufgabe sollte so einfach und natürlich C# zu lösen sein, wie es schon immer mit Visual Basic der Fall war. Dies ist außerdem Bestandteil der Strategie für eine gemeinsame Entwicklung von Visual Basic und C#: Beide Sprachen streben eine Gleichmäßigkeit in der Funktionalität an und nutzen die produktivsten Lösungen der anderen Sprache.

Wenn Sie sich für die Details interessieren, lesen Sie "Die gemeinsame Entwicklung von C# und VB" im Visual Studio-Blog von Scott Wiltamuth (bit.ly/bFUpxG, möglicherweise in englischer Sprache).

Abbildung 3 zeigt den C# 4-Code, der der ersten Zelle in einem Excel-Arbeitsblatt einen Wert hinzufügt und anschließend die AutoFit-Methode auf die erste Spalte anwendet. Die Kommentare unterhalb der einzelnen Zeilen zeigen die Entsprechungen in C# 3.0 und früheren Versionen.

Abbildung 3 Skripterstellung für Excel mit C#

// Add this line to the beginning of the file:
// using Excel = Microsoft.Office.Interop.Excel;

var excelApp = new Excel.Application();

excelApp.Workbooks.Add();
// excelApp.Workbooks.Add(Type.Missing);

excelApp.Visible = true;

Excel.Range targetRange = excelApp.Range["A1"];
// Excel.Range targetRange = excelApp.get_Range("A1", Type.Missing);

targetRange.Value = "Name";
// targetRange.set_Value(Type.Missing, "Name");

targetRange.Columns[1].AutoFit();
// ((Excel.Range)targetRange.Columns[1, Type.Missing]).AutoFit();

Das Interessante an diesem Beispiel ist, dass Sie das dynamic-Schlüsselwort nirgendwo im Code sehen. Es wird nur in einer einzigen Zeile verwendet:

targetRange.Columns[1].AutoFit();
// ((Excel.Range)targetRange.Columns[1, Type.Missing]).AutoFit();

In C# 3.0 gibt targetRange.Columns[1, Type.Missing] ein Objekt zurück. Daher ist die Umwandlung zu Excel.Range erforderlich. In C# 4 und Visual Studio 2010 werden solche Aufrufe jedoch still zu dynamischen Aufrufen konvertiert. Daher ist der Typ von targetRange.Columns[1] in C# 4 tatsächlich dynamisch.

Eine andere hervorzuhebende Tatsache ist, dass die Verbesserungen für die COM-Interoperabilität in C# 4 nicht nur deren dynamisches Verhalten betrifft. In allen anderen Zeilen wird aufgrund anderer neuer Funktionen wie indexierter Eigenschaften sowie benannter und optionaler Parameter eine bessere Syntax ermöglicht. Eine gute Übersicht über diese neuen Funktionen finden Sie im MSDN-Magazin-Artikel "Neue C#-Funktionen in .NET Framework 4" von Chris Burrows (msdn.microsoft.com/magazine/ff796223, möglicherweise in englischer Sprache).

Wo gibt es mehr Informationen?

Hoffentlich hat dieser Artikel die meisten Fragen abgedeckt, die Sie möglicherweise zum dynamic-Schlüsselwort in C# 4 haben. Ich bin mir jedoch sicher, dass ich nicht alles behandelt habe. Wenn Sie Kommentare, Fragen oder Vorschläge haben, besuchen Sie dlr.codeplex.com/discussions. Möglicherweise hat ein anderer Programmierer bereits eine Frage zu diesem Problem gestellt. Sie können auch eine neue Diskussion starten. Wir haben eine aktive Community und freuen uns über neue Mitglieder.

Alexandra Rusina ist Program Manager im Silverlight-Team. Zuvor arbeitete sie im Visual Studio Languages-Team für die Visual Studio 2010-Version als Programmiererin und Autorin. Sie verfasst außerdem regelmäßig Beiträge für den C# FAQ-Blog (blogs.msdn.com/b/csharpfaq/).

Unser Dank gilt dem folgenden technischen Experten für die Durchsicht dieses Artikels: Bill Chiles