Sonderausgabe 2015 zu Windows 10

Band 30, Nummer 11

Microsoft .NET – .NET und die Entwicklung für die universelle Windows-Plattform

Von Daniel Jacobson | Windows 2015

Mithilfe von Visual Studio 2015 können Sie nun die neueste .NET-Technologie zum Entwickeln von UWP-Anwendungen (Universelle Windows-Plattform) nutzen, die auf allen Windows 10-Geräten ausgeführt werden. Dazu zählen das Smartphone in Ihrer Hosen- bzw. Jackentasche, der Laptop oder das Tablet in Ihrer Umhängetasche, der Surface Hub in Ihrem Büro, die Xbox-Konsole bei Ihnen Zuhause, HoloLens und alle anderen im Internet of Things (IoT, Internet der Dinge) möglichen Geräte. Dies ist eine wirklich aufregende Zeit für Windows-Entwickler.

Was hat die UWP Neues zu bieten?

Als .NET-Entwickler werden Sie alles zu schätzen wissen, was die UWP zu bieten hat. Die UWP wird im "Fenstermodus" auf einer großen Anzahl von Desktops ausgeführt, für die bereits ein Upgrade auf Windows 10 erfolgt ist bzw. bei denen es noch ansteht. UWP-Apps sind in der Lage, alle Windows 10-Geräte mittels eines Anwendungspakets und einer Codebasis zu erreichen. Darüber hinaus nutzen UWP-Apps das neue Microsoft .NET Core Framework (was weiter unten in diesem Artikel ausführlich vorgestellt wird). Ihre .NET-Geschäftslogik kann auf anderen Plattformen ausgeführt werden, die .NET Core unterstützen, wie z. B. ASP.NET 5. UWP-Apps stellen eine kleine Kopie von .NET Core mit der App bereit, weshalb Apps stets mit der .NET-Version ausgeführt werden, für die Sie sie getestet haben. Alle .NET UWP-Apps kommen in den Genuss von .NET Native, das einen überaus optimierten systemeigenen Maschinencode generiert, was zu Leistungssteigerungen führt (und auch in diesem Artikel erläutert wird).

.NET Core Framework

.NET Core Framework ist eine neue Version von .NET für moderne Geräte und Cloudworkloads. Es handelt sich um eine allgemeine und modulare Microsoft .NET Framework-Implementierung, die für eine Vielzahl von Workloads portiert und in vielen verschiedenen Umgebungen eingesetzt werden kann. .NET Core Framework ist darüber hinaus Open Source auf GitHub (github.com/dotnet/corefx) verfügbar und wird von Microsoft unter Windows, Linux und Mac OS X unterstützt. Wenn Sie als UWP-Entwickler mit der neuesten .NET-Technologie arbeiten, bringt Ihnen das viele Vorteile. In Visual Studio 2015 können Sie die .NET Core PCLs (Portable Class Libraries) nutzen, um sämtliche UWP-Apps, .NET 4.6-Apps und ASP.NET 5-Apps als Ziel auszuwählen, auch wenn diese plattformübergreifend sind.

Zudem ist .NET Core Framework eine Obermenge der .NET-APIs, die zuvor für die Entwicklung von Windows Store-Apps zur Verfügung standen. Dies bedeutet, dass UWP-Entwicklern nun mehrere zusätzliche Namespaces in ihrer API-Palette zur Verfügung stehen. Einer dieser Namespaces ist "System.Net.Sockets", der für die UDP-Kommunikation verwendet wird. Dieser Namespace war zuvor in WinRT-Apps (Windows Runtime) nicht verfügbar, weshalb behelfsmäßig die WinRT-spezifischen UDP-APIs verwendet werden mussten. Nun da "System.Net.Sockets" in .NET Core zur Verfügung steht, können Sie denselben "Socket"-Code in Ihren UWP- und anderen .NET-Apps einsetzen.

Ein weiterer Vorteil ist, dass die "System.Net.Http.HttpClient"-API auf den WinRT-HTTP-Stapeln basiert. Dies ermöglicht, dass standardmäßig HTTP/2 verwendet wird, falls vom Server unterstützt, was zu kürzeren Wartezeiten und weniger Roundtrips führt.

Der WCF-Client (Windows Communication Foundation) (und das dazugehörige Dialogfeld "Dienstverweis hinzufügen") war zuvor in APPX-Projekten für Windows Phone nicht verfügbar, doch da er Teil von .NET Core ist, kann er für alle .NET-basierten UWP-Apps verwendet werden.

Schließlich ist .NET Core das zugrunde liegende Framework, von dem .NET Native abhängt. Bei der Entwicklung von .NET Native war klar, dass .NET Framework nicht als Grundlage für die Klassenbibliotheken des Frameworks geeignet sein würde. Der Grund ist, dass .NET Native das Framework statisch mit der Anwendung verknüpft und anschließend die Zusatzelemente entfernt, die von der Anwendung nicht benötigt werden. (Dies ist eine grobe Vereinfachung, doch Sie bekommen eine Vorstellung. Weitere Einzelheiten erfahren Sie in "Inside .NET Native" unter bit.ly/1UR7ChW.)

Die herkömmliche .NET Framework-Implementierung ist nicht gut strukturiert, wodurch ein Linker vor der Herausforderung steht, die Menge an Framework zu reduzieren, die in die Anwendung kompiliert wird. .NET Core ist schließlich im Wesentlichen eine Verzweigung von .NET Framework, dessen Implementierung hinsichtlich Strukturierungsaspekten optimiert wurde. Ein weiterer Vorteil dieser Implementierung ist die Möglichkeit der Übertragung von .NET Core Framework als Gruppe von NuGet-Paketen dergestalt, dass Sie die einzelnen Klassen Out-of-Band in .NET Framework aktualisieren können. Doch bevor wir dies vertiefen, lassen Sie uns die Änderungen in NuGet ansprechen.

Neuerungen in NuGet

Die UWP bietet integrierte Unterstützung für NuGet 3.1. Diese Version bietet Features zum Verbessern der Verwaltung von Paketabhängigkeiten und eine lokale Cachespeicherung Ihrer Pakete zur Wiederverwendung in mehreren Projekten.

In NuGet 3.1 wurde das Modell für die Deklaration von Paketabhängigkeiten aktualisiert. Ab ASP.NET 5 bietet NuGet Unterstützung für die Datei "project.json", wobei es sich um dasselbe Modell handelt, das von der UWP unterstützt wird. Die Datei "project.json" ermöglicht Ihnen das Beschreiben der Abhängigkeiten eines Projekts mit einer klaren Definition der Pakete, von denen Sie letztlich abhängig sind. Da das Format für ASP.NET 5 und die UWP identisch ist, können Sie dieselbe Datei nutzen, um sowohl Paketverweise für beide Plattformen als auch PCLs zu definieren.

Durch den Wechsel von "packages.config" zu "project.json" können Sie die Verweise in Ihren Projekten "neu starten". Außerdem gibt es jetzt eine neue transitive Abhängigkeitsfunktion von NuGet. Wenn Sie auf ein Paket verweisen, das auf andere NuGet-Pakete verweist, war die Paketversionsverwaltung bislang schwierig. Beispiel: NHibernate ist ein von "lesi.Collections" abhängiges Paket. Die Datei "packages.config" enthält zwei Verweise, einen für jedes Paket. Wenn Sie NHibernate aktualisieren möchten, aktualisieren Sie dann auch "lesi.collections"? Oder müssen Sie, wenn es eine Aktualisierung für "lesi.collections" gibt, auch NHibernate aktualisieren, um die neuen Features zu unterstützen? Dies alles führte zu einem unübersichtlichen Zyklus, und auch die Paketversionsverwaltung gestaltete sich schwierig. Das transitive Abhängigkeitsfeature von NuGet abstrahiert diese Entscheidung zum Aktualisieren von Paketverweisen mithilfe einer verbesserten semantischen Versionsverwaltung in der Paketdefinitionsdatei (.nuspecs).

Darüber hinaus wird von NuGet nun eine Kopie der Pakete heruntergeladen und gespeichert, die Sie im Ordner für globale Pakete in Ihrem Ordner "%userprofile%\.nuget\packages" verwenden. Dadurch wird nicht durch die Leistung von Paketverweisen verbessert, da Sie jedes Paket nur einmal herunterladen müssen, sondern auch weniger Speicherplatz auf dem Datenträger Ihrer Arbeitsstation belegt, da dieselben Paketbinärdateien von verschiedenen Projekten gemeinsam genutzt werden können.

NuGet und .NET Core

Was passiert, wenn Sie .NET Core mit dem Fokus auf Strukturierung verwenden und mit der Verwaltung von Paketabhängigkeiten von NuGet 3.1 kombinieren? Sie erhalten die Möglichkeit, einzelne .NET Framework-Pakete Out-of-Band vom Rest von .NET Framework zu aktualisieren. Bei der UWP ist .NET Core als eine Gruppe von NuGet-Paketen in Ihrer App vorhanden. Wenn Sie ein neues Projekt erstellen, wird Ihnen nun die allgemeine "Microsoft.NETCore.UniversalWindowsPlatform"-Paketabhängigkeit angezeigt. Doch wenn Sie sich dieses Paket auf NuGet ansehen, erkennen Sie alle enthaltenen .NET Framework-Bibliotheken (siehe Abbildung 1).

Anzeigen von .NET Framework-Bibliotheken in NuGet
Abbildung 1: Anzeigen von .NET Framework-Bibliotheken in NuGet

Angenommen, es gibt eine Aktualisierung der "System.Net.Sockets"-Klasse, mit der eine neue API eingeführt wird, die Sie in Ihrer Anwendung verwenden. Bei herkömmlichem .NET müsste Ihre Anwendung eine Abhängigkeit vom neuen Build des gesamten .NET Framework verwenden. Bei der UWP und .NET Core mit NuGet können Sie Ihre NuGet-Abhängigkeiten so aktualisieren, dass nur die neueste Version dieses Pakets einbezogen wird. Wenn anschließend Ihre Anwendung kompiliert und zu einem Paket zusammengestellt wird, wird diese Version der Frameworkbibliothek in Ihre Anwendung einbezogen. Dadurch können Sie flexibel die neueste und beste .NET-Technologie nutzen, ohne die Benutzer zu zwingen, stets das neueste Framework auf ihren Geräten installieren zu müssen.

Sie sind jetzt nicht nur in der Lage, Ihre .NET-Klassen im eigenen Tempo zu aktualisieren, sondern das auf Komponenten basierende .NET Core ermöglicht auch .NET Native. Dadurch ergeben sich Leistungszuwächse bei der Bereitstellung von Windows 10-Anwendung auf C#- und Visual Basic-Basis auf Endbenutzergeräten.

Was ist .NET Native?

Nachdem Sie erfahren haben, dass .NET Native von .NET Core Framework ermöglicht wird, möchte ich nun detaillierter erläutern, was .NET Native ist und welche Vorteile es für Sie als UWP-Entwickler bietet.

.NET Native ist ein vorzeitiger Kompilierungsprozess, der Ihren verwalteten .NET-Code zur Kompilierzeit in systemeigenen Maschinencode umwandelt. Im Gegensatz dazu arbeitet herkömmliches .NET mit einer JIT-Kompilierung (Just-In-Time), die die systemeigene Kompilierung einer Methode bis zur ersten Ausführung zur Laufzeit zurückstellt. .NET Native ist einem C++-Compiler ähnlicher und verwendet tatsächlich den Visual Studio C++-Compiler als Teil seiner Toolkette. Alle verwalteten universellen Windows-App (C# oder Visual Basic) nutzen diese neue Technologie. Die Anwendungen werden automatisch zu systemeigenem Code kompiliert, ehe sie die Endbenutzergeräte erreichen. Wenn es Sie interessieren sollte, wie dies im Detail funktioniert, empfehle ich Ihnen den MSDN Library-Artikel "Kompilieren von Anwendungen mit .NET Native" unter bit.ly/1QcTGxm.

Wir wirkt sich .NET Native auf Sie und Ihre App aus?

Dies kann im Einzelfall variieren, doch in den meisten Fällen wird Ihre App schneller gestartet, eine bessere Leistung bringen und weniger Systemressourcen belegen. Sie können beim ersten Start Ihrer Anwendung eine um 60 % bessere Leistung und bei nachfolgenden Starts eine um 40 % bessere Leistung erwarten. Bei systemeigener Kompilierung belegen Ihre Anwendungen weniger Arbeitsspeicher. Alle Abhängigkeiten von der .NET-Laufzeit werden entfernt, sodass Ihre Endbenutzer Ihr Setup nicht unterbrechen müssen, um die spezifische .NET Framework-Version zu beziehen, auf die Ihre Anwendung verweist. Tatsächlich sind alle .NET-Abhängigkeiten innerhalb Ihrer Anwendung gepackt, weshalb sich das Verhalten Ihrer App nicht ändern sollte, bloß weil es auf dem jeweiligen Computer eine Änderung beim installierten .NET Framework gibt.

Auch wenn Ihre Anwendung zu systemeigenen Binärdateien kompiliert wird, können Sie weiter die .NET-Sprachen, mit denen Sie vertraut sind (C# oder Visual Basic) und die ausgezeichneten Tools nutzen, die dazu gehören. Schließlich können Sie weiter das umfangreiche und einheitliche Programmiermodell in .NET Framework zusammen mit den zahlreichen APIs für Geschäftslogik, der integrierten Arbeitsspeicherverwaltung und der Ausnahmebehandlung nutzen.

Mit .NET Native erhalten Sie das beste beider Welten, nämlich eine verwaltete Entwicklung mit C++-Leistung. Wie cool ist das denn?

Debug- im Vergleich zur Release-/Kompilierungskonfiguration

Die .NET Native-Kompilierung ist ein komplexer Prozess, der ein wenig langsamer als die klassische .NET-Kompilierung erfolgt. Die zuvor erwähnten Vorteile gehen auf Kosten der Kompilierzeit. Sie können wählen, dass die Kompilierung immer dann systemeigen erfolgen soll, wenn Sie Ihre App ausführen. Doch dann müssen Sie länger warten, bis der Build abgeschlossen wird. Die Visual Studio-Tools sind darauf ausgelegt, dies in den Griff zu bekommen und für eine möglichst reibungslose Entwicklererfahrung zu sorgen.

Wenn Sie für Ihren Code Builds erstellen und ihn in der "Debug"-Konfiguration ausführen, führen Sie Intermediate Language-Code für die in Ihrer Anwendung gepackte CoreCLR aus. Die .NET-Systemassemblys sind neben Ihrem Anwendungscode gepackt, und Ihre Anwendung verwendet eine Abhängigkeit vom Microsoft.NET.CoreRuntime-Paket (CoreCLR). Wenn das CoreCLR-Framework auf dem Gerät fehlt, auf dem Sie testen, wird dies von Visual Studio automatisch erkannt, woraufhin es installiert wird, bevor Sie Ihre Anwendung bereitstellen.

Das heißt, dass Sie die bestmögliche Entwicklungserfahrung erhalten: schnelle Kompilierung und Bereitstellung, umfassende Debugging- und Diagnosefunktionen sowie alle Tools, mit denen Sie bei der .NET-Entwicklung vertraut sind.

Wenn Sie in den Modus "Release" wechseln, nutzt Ihre App standardmäßig die .NET Native-Toolkette. Da das Paket zu systemeigenen Binärdateien kompiliert wird, muss das Paket nicht die .NET Framework-Bibliotheken enthalten. Darüber hinaus ist das Paket von der neuesten installierten .NET Native-Runtime und nicht vom CoreCLR-Paket abhängig. Die .NET Native-Runtime auf dem Gerät ist stets mit Ihrem Anwendungspaket kompatibel.

Die lokale systemeigene Kompilierung über die "Release"-Konfiguration ermöglicht das Testen Ihrer Anwendung in einer Umgebung, die der Ihrer Kunden ähnlich ist. Sie müssen dies unbedingt regelmäßig testen, sobald Sie mit der Entwicklung fortfahren! Indem Sie Ihre Anwendung mithilfe der Codegenerierungs- und Laufzeittechnologie testen, die Sie Ihren Kunden bieten, stellen Sie sicher, dass Sie alle möglichen Programmfehler im Griff haben (z. B. potenzielle Racebedingungen, die sich aus unterschiedlichen Leistungsmerkmalen ergeben).

Eine bewährte Methode ist das regelmäßige Testen Ihrer App auf diese Weise während der gesamten Entwicklung, um sicherzustellen, dass Sie sämtliche vom .NET Native-Compiler stammenden Probleme bestimmen und beheben. In den meisten Fällen sollte es keine Probleme geben, doch es gibt einige Dinge, die bei .NET Native nicht so glatt laufen. Ein Beispiel sind mehr als vier dimensionale Arrays. Schlussendlich erhalten Ihre Kunden die kompilierte .NET Native-Version Ihrer Anwendung, weshalb es sich stets empfiehlt, diese Version während der gesamten Entwicklung und vor der Auslieferung zu testen.

Neben dem Testen mit der .NET Native-Kompilierung wird Ihnen auch aufgefallen sein, dass die Buildkonfiguration "AnyCPU" nicht mehr da ist. Bei .NET Native ist AnyCPU keine gültige Buildkonfiguration mehr, da die systemeigene Kompilierung architekturabhängig ist. Eine weitere Folge hiervon ist, dass Sie beim Packen Ihrer Anwendung alle drei Architekturkonfigurationen (x86, x64 und ARM) auswählen müssen, um sicherzustellen, dass Ihre Anwendung auf so vielen Geräten wie möglich läuft. Dies ist schließlich die universelle Windows-Plattform.

Vor diesem Hintergrund können Sie weiter AnyCPU-Bibliotheken und -DLLs erstellen, auf die in Ihrer UWP-App verwiesen werden soll. Diese Komponenten werden basierend auf der Konfiguration des Projekts (.appx), das sie nutzt, zu architekturspezifischen Binärdateien kompiliert.

.NET Native in der Cloud

Ein besonderes Merkmal von .NET Native ist, dass der Compiler in der Cloud gehostet werden kann. Dies bedeutet, dass wenn Verbesserungen am Compiler erfolgen, die ggf. eine positive Auswirkung auf Ihre Anwendung haben, der in der Cloud gehostete .NET Native-Compiler im Store Ihr Anwendungspaket neu kompilieren kann, damit es in den Genuss der Vorteile kommt. Immer wenn diese Kompilierung stattfindet, merken Sie als Entwickler nichts davon, doch die Kunden Ihrer Anwendung werden noch zufriedener sein.

Dieser Prozess kann allerdings Auswirkungen auf Ihren Workflow haben. Es empfiehlt sich beispielsweise sicherzustellen, dass Sie die neuesten Tools installiert haben, damit Sie Ihre .NET Native-Kompilierung mit der neuesten lokalen Version des Compilers testen können. Außerdem werden beim Erstellen Ihres "Store"-Pakets in Visual Studio zwei Pakete erstellt: eines vom Typ ".appxupload" und eine Test-APPX-Datei für das Sideloaden. Das APPXUPLOAD-Paket enthält die MSIL-Binärdateien sowie einen expliziten Verweis auf die Version der .NET Native-Toolkette, die Ihre Anwendung nutzt (in der Datei "AppxManifest.xml" als "ilc.exe" referenziert). Dieses Paket wechselt dann in den Store und wird mit exakt derselben Version der .NET Native-Toolkette kompiliert. Da der Compiler in der Cloud gehostet wird, kann eine Iteration zum Beheben von Programmfehlern erfolgen, ohne dass Sie Ihre App erneut lokal kompilieren müssen.

Bei .NET Native müssen Sie achtsam sein, welches Paket Sie in den Store hochladen. Da der Store die systemeigene Kompilierung für Sie übernimmt, können Sie nicht die systemeigenen Binärdateien hochladen, die vom lokalen .NET Native-Compiler generiert werden. Der Visual Studio-Workflow begleitet Sie so durch den Prozess, dass Sie das richtige Paket auswählen. Einen umfassenden Leitfaden zum Erstellen eines Store-Pakets finden Sie im MSDN Library-Artikel "Verpacken von universellen Windows-Apps für Windows 10" unter bit.ly/1OQTTG0. Dieser Artikel begleitet Sie durch das Erstellen von Paketen, um sicherzustellen, dass Sie das richtige Paket erzeugen und für das Hochladen in den Store auswählen.

Debugging mit .NET Native

Wenn Sie in Ihrer Anwendung Probleme feststellen, die Ihrer Ansicht nach von .NET Native verursacht werden, gibt es eine Methode zum Beheben des Problems. Bei "Release"-Konfigurationen wird der Code standardmäßig vollständig optimiert (z. B. findet an vielen Stellen das Inlining von Code statt), wobei einige der Debuggingartefakte verloren gehen. Das hat zur Folge, dass das Debuggen einer "Release"-Konfiguration schwierig sein kann. Das Verhalten beim schrittweisen Durchlaufen des Codes und Setzen von Haltepunkten kann ggf. unvorhersehbar sein. Je nachdem ist auch das Untersuchen von Variablen aufgrund von Speicheroptimierungen nicht möglich. Da das Standardverhalten von "Release"-Konfigurationen die Verwendung des .NET Native-Compilers mit Codeoptimierung vorsieht, ist das Debuggen von Problemen schwierig, die die Folge des .NET Native-Kompilierungsprozesses sein können.

Eine gute Möglichkeit, dies zu umgehen, ist das Erstellen einer angepassten Buildkonfiguration für Ihr Projekt, die den .NET Native-Compiler nutzt, aber den Code nicht vollständig optimiert. Öffnen Sie zum Erstellen einer angepassten Buildkonfiguration den Konfigurations-Manager in der Dropdownliste "Buildkonfiguration" (siehe Abbildung 2).

Öffnen des Konfigurations-Managers
Abbildung 2: Öffnen des Konfigurations-Managers

Wählen Sie in der Dropdownliste "Konfiguration der aktuellen Projektmappe" die Option "<Neu…>" aus, um eine neue Konfiguration zu erstellen (siehe Abbildung 3).

Erstellen einer neuen Konfiguration
Abbildung 3: Erstellen einer neuen Konfiguration

Geben Sie der neuen Konfiguration einen aussagekräftigen Namen. Ich wähle meist etwas wie ".NET Native debuggen". Kopieren Sie die Einstellungen aus der "Release"-Buildkonfiguration, und klicken Sie auf "OK".

Schließen Sie den Konfigurations-Manager, und öffnen Sie die Eigenschaftenseite des Projekts, indem Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt klicken und dann auf "Eigenschaften" klicken. Navigieren Sie zur Registerkarte "Build". Vergewissern Sie sich, dass "Mit .NET Native-Toolkette kompilieren" aktiviert und "Code optimieren" deaktiviert ist (siehe Abbildung 4).

Erstellen einer Buildkonfiguration zum Debuggen von .NET Native
Abbildung 4: Erstellen einer Buildkonfiguration zum Debuggen von .NET Native

Sie verfügen nun über eine Buildkonfiguration, mit der Sie .NET Native-spezifische Probleme beheben können.

Weitere Informationen zum Debugging mit .NET Native finden Sie im MSDN Library-Blogartikel "Debugging .NET Native Windows Universal Apps" unter bit.ly/1Ixd07v.

.NET Native Analyzer

Es ist sicherlich gut zu wissen, wie Probleme behoben werden, doch wäre es nicht besser, wenn Sie diese von vornherein vermeiden könnten? Der Microsoft.NETNative.Analyzer (bit.ly/1LugGnO) kann über NuGet in Ihre Anwendung installiert werden. Das Paket kann über die Paket-Manager-Konsole mit dem folgenden Befehl installiert werden: Install-Package Microsoft.NETNative.Analyzer. Dieses Analysemodul gibt zur Entwicklungszeit Warnungen aus, wenn Ihr Code nicht mit dem .NET Native-Compiler kompatibel ist. Es gibt einen kleinen Abschnitt der .NET-Oberfläche, der nicht kompatibel ist, doch bei der Mehrheit der Apps wird dies nie ein Problem sein.

Schlussbemerkungen

Wie Sie sehen, ist dies eine aufregende Zeit für .NET-Windows-Entwickler. Dank UWP, .NET Native und Änderungen an NuGet war es nie zuvor einfacher, Apps für so viele verschiedene Geräte zu entwickeln, die Ihre Kunden lieben werden. Zum ersten Mal können Sie in den Genuss der neuesten Fortschritte bei beliebigen .NET-Klassen kommen und dennoch erwarten, dass Ihre Anwendung auf allen Windows 10-Geräte läuft.


Daniel Jacobsonist ein Programm-Manager für Visual Studio und arbeitet an Tools für Entwickler für die Windows-Plattform. Sie erreichen Ihn unter dajaco@microsoft.com.

Unser Dank gilt den folgenden technischen Experten für die Durchsicht dieses Artikels: Kino Aguilar, Adam Denning, Yishai Galatzer, Jenny Hayes, Jeremy Meng, Harikrishna Menon, Jessica Prince, Unni Ravindranathan, Navit Saxena, Michael Strehovsky, Debbie Thorn, Matthew Whilde, Lucian Wischik