Migrieren Ihrer Windows 8.x-App zu .NET Native

.NET Native ermöglicht die statische Kompilierung von Apps im Microsoft Store oder auf dem Computer des Entwicklers. Dies unterscheidet sich von der dynamischen Kompilierung, die für Windows 8.x-Apps (auch zuvor als Microsoft Store-Apps bezeichnet) durch den JIT-Compiler (Just-In-Time) oder den nativen Imagegenerator (Ngen.exe) auf dem Gerät durchgeführt wird. Trotz der Unterschiede versucht .NET Native, die Kompatibilität mit .NET für Windows 8.x-Apps aufrechtzuerhalten. In den meisten Fällen funktionieren Dinge, die in .NET für Windows 8.x-Apps funktionieren, auch mit .NET Native. In einigen Fällen können jedoch Verhaltensänderungen auftreten. In diesem Dokument werden diese Unterschiede zwischen den standardmäßigen .NET für Windows 8.x-Apps und .NET Native in den folgenden Bereichen erläutert:

Allgemeine Laufzeitunterschiede

  • Ausnahmen wie TypeLoadException, die vom JIT-Compiler ausgelöst werden, wenn eine App in der Common Language Runtime (CLR) ausgeführt wird, führen in der Regel zu Kompilierzeitfehlern, wenn sie von .NET Native verarbeitet werden.

  • Rufen Sie die GC.WaitForPendingFinalizers -Methode nicht vom UI-Thread einer Anwendung auf. Dies kann zu einem Deadlock für .NET Native führen.

  • Verlassen Sie sich nicht auf die Aufrufreihenfolge des statischen Klassenkonstruktors. In .NET Native unterscheidet sich die Aufrufreihenfolge von der Reihenfolge in der Standardlaufzeit. (Auch mit der Standardlaufzeit sollten Sie sich nicht auf die Reihenfolge der Ausführung der statischen Klassenkonstruktoren verlassen.)

  • Endlosschleifen ohne einen Anruf (z. B. while(true);) auf einem beliebigen Thread kann die App zum Stillstand bringen. Auf ähnliche Weise können lange oder unendliche Wartezeiten die Anwendung zum Stillstand bringen.

  • Bestimmte generische Initialisierungszyklen lösen keine Ausnahmen in .NET Native aus. Das folgende Codebeispiel löst eine TypeLoadException -Ausnahme auf der Standard-CLR aus. In .NET Native nicht.

    using System;
    
    struct N<T> {}
    struct X { N<X> x; }
    
    public class Example
    {
       public static void Main()
       {
          N<int> n = new N<int>();
          X x = new X();
       }
    }
    
  • In einigen Fällen stellt .NET Native verschiedene Implementierungen von .NET Framework Klassenbibliotheken bereit. Ein von einer Methode zurückgegebenes Objekt implementiert immer die Member des zurückgegebenen Typs. Da aber die Unterstützungsimplementierung unterschiedlich ist, können Sie es möglicherweise nicht in dieselben Typen wie auf anderen .NET Framework-Plattformen umwandeln. In einigen Fällen sind Sie zum Beispiel möglicherweise nicht in der Lage, das IEnumerable<T> -Schnittstellenobjekt, das von Methoden wie TypeInfo.DeclaredMembers oder TypeInfo.DeclaredProperties zurückgegeben wird, in T[]umzuwandeln.

  • Der WinInet-Cache ist in .NET für Windows 8.x-Apps nicht standardmäßig aktiviert, aber .NET Native. Dies verbessert die Leistung, hat aber Auswirkungen auf das Workingset. Es ist keine Entwickleraktion erforderlich.

Dynamische Programmierunterschiede

.NET Native statische Verknüpfungen im Code aus .NET Framework, um den Code app-lokal zu machen, um maximale Leistung zu erzielen. Binäre Größen müssen jedoch klein bleiben, sodass nicht das gesamte .NET Framework einbezogen werden kann. Der .NET Native Compiler löst diese Einschränkung mithilfe eines Abhängigkeitsminderers auf, der Verweise auf nicht verwendeten Code entfernt. .NET Native verwaltet oder generiert jedoch möglicherweise keine Typinformationen und Code, wenn diese Informationen zur Kompilierzeit nicht statisch abgeleitet werden können, sondern dynamisch zur Laufzeit abgerufen werden.

.NET Native ermöglicht Reflektion und dynamische Programmierung. Allerdings können nicht alle Typen zur Reflektion markiert werden, da dies die generierte Codegröße zu groß machen würde (insbesondere, weil die Reflektion öffentlicher APIs in .NET Framework unterstützt wird). Der .NET Native Compiler trifft intelligente Entscheidungen darüber, welche Typen reflektion unterstützen sollen, behält die Metadaten bei und generiert nur Code für diese Typen.

Beispielsweise erfordert die Datenbindung, dass eine App Eigenschaftennamen Funktionen zuordnen kann. In .NET für Windows 8.x-Apps verwendet die Common Language Runtime automatisch Reflektion, um diese Funktion für verwaltete Typen und öffentlich verfügbare native Typen bereitzustellen. In .NET Native schließt der Compiler automatisch Metadaten für Typen ein, an die Sie Daten binden.

Der .NET Native Compiler kann auch häufig verwendete generische Typen wie List<T> und Dictionary<TKey,TValue>verarbeiten, die ohne Hinweise oder Direktiven funktionieren. Das dynamic -Schlüsselwort wird ebenfalls innerhalb bestimmter Grenzen unterstützt.

Hinweis

Sie sollten alle dynamischen Codepfade gründlich testen, wenn Sie Ihre App zu .NET Native portieren.

Die Standardkonfiguration für .NET Native ist für die meisten Entwickler ausreichend, aber einige Entwickler möchten möglicherweise ihre Konfigurationen mithilfe einer Laufzeitdirektivendatei (.rd.xml) optimieren. Darüber hinaus kann der .NET Native Compiler in einigen Fällen nicht ermitteln, welche Metadaten für die Reflektion verfügbar sein müssen, und stützt sich insbesondere in den folgenden Fällen auf Hinweise:

  • Einige Konstrukte wie Type.MakeGenericType und MethodInfo.MakeGenericMethod können nicht statisch bestimmt werden.

  • Da der Compiler die Instanziierungen nicht ermitteln kann, muss ein generischer Typ, den Sie für die Reflektion verwenden möchten, durch Laufzeitdirektiven angegeben werden. Nicht nur, weil der gesamte Code enthalten sein muss, sondern auch, weil die Reflektion für generische Typen (z. B. wenn eine generische Methode für einen generischen Typ aufgerufen wird) einen unendlichen Zyklus bilden kann.

Hinweis

Laufzeitdirektiven werden in einer Laufzeitdirektivendatei (.rd.xml) definiert. Allgemeine Informationen zur Verwendung dieser Datei finden Sie unter Getting Started with .NET Native (Erste Schritte mit .NET Native). Informationen zu Laufzeitdirektiven finden Sie unter Runtime Directives (rd.xml) Configuration File Reference.

.NET Native enthält auch Profilerstellungstools, mit denen Entwickler ermitteln können, welche Typen außerhalb des Standardsatzes Reflektion unterstützen sollen.

Zwischen .NET für Windows 8.x-Apps und .NET Native gibt es eine Reihe weiterer individueller Reflexionsunterschiede.

In .NET Native:

  • Private Reflektion über Typen und Member in der .NET Framework-Klassenbibliothek wird nicht unterstützt. Sie können jedoch eigene private Typen und Member sowie Typen und Member in Bibliotheken von Drittanbietern für die Reflektion verwenden.

  • Die ParameterInfo.HasDefaultValue -Eigenschaft gibt ordnungsgemäß false für ein ParameterInfo -Objekt zurück, das einen Rückgabewert darstellt. In .NET für Windows 8.x-Apps wird zurückgegeben true. Intermediate Language (IL) unterstützt dies nicht direkt, und die Interpretation bleibt der Sprache überlassen.

  • Öffentliche Member in den RuntimeFieldHandle - und RuntimeMethodHandle -Strukturen werden nicht unterstützt. Diese Typen werden nur für LINQ, Ausdrucksbaumstrukturen und statische Arrayinitialisierungen unterstützt.

  • RuntimeReflectionExtensions.GetRuntimeProperties und RuntimeReflectionExtensions.GetRuntimeEvents enthalten ausgeblendete Member in Basisklassen und können daher ohne explizite Überschreibungen überschrieben werden. Dies gilt auch für andere RuntimeReflectionExtensions.GetRuntime* -Methoden.

  • Type.MakeArrayType und Type.MakeByRefType schlagen nicht fehl, wenn Sie versuchen, bestimmte Kombinationen (z. B. ein Array von byref Objekten) zu erstellen.

  • Sie können mithilfe der Reflektion keine Member mit Zeigerparametern aufrufen.

  • Sie können mithilfe der Reflektion kein Zeigerfeld abrufen oder festlegen.

  • Wenn die Argumentanzahl falsch ist und der Typ eines der Argumente falsch ist, löst .NET Native anstelle eines aus ArgumentExceptionTargetParameterCountException.

  • Binäre Serialisierung von Ausnahmen wird in der Regel nicht unterstützt. Daher können nicht serialisierbare Objekte zum Exception.Data -Wörterbuch hinzugefügt werden.

Nicht unterstützte Szenarios und APIs

In den folgenden Abschnitten werden nicht unterstützte Szenarios und APIs für allgemeine Entwicklung, Interop und Technologien wie HTTPClient und Windows Communication Foundation (WCF) aufgelistet:

Allgemeine Entwicklungsunterschiede

Werttypen

  • Wenn Sie die ValueType.Equals - und ValueType.GetHashCode -Methoden für einen Werttyp außer Kraft setzen, rufen Sie nicht die Implementierungen der Basisklasse auf. In .NET für Windows 8.x-Apps basieren diese Methoden auf Reflektion. Zur Kompilierzeit generiert .NET Native eine Implementierung, die nicht auf der Laufzeitreflektion basiert. Dies bedeutet, dass diese beiden Methoden, wenn Sie diese beiden Methoden nicht überschreiben, wie erwartet funktionieren, da .NET Native die Implementierung zur Kompilierzeit generiert. Allerdings wird durch das Außerkraftsetzen dieser Methoden und das Aufrufen der Basisklassenimplementierung eine Ausnahme ausgelöst.

  • Werttypen, die größer als 1 Megabyte sind, werden nicht unterstützt.

  • Werttypen dürfen keinen parameterlosen Konstruktor in .NET Native haben. (C# und Visual Basic verbieten parameterlose Konstruktoren für Werttypen. Diese können jedoch in IL erstellt werden.)

Arrays

  • Arrays mit einer unteren Grenze ungleich null werden nicht unterstützt. Diese Arrays werden in der Regel durch Aufrufen der Array.CreateInstance(Type, Int32[], Int32[]) -Überladung erstellt.

  • Die dynamische Erstellung von mehrdimensionalen Arrays wird nicht unterstützt. Solche Arrays werden in der Regel durch Aufruf einer Überladung für die Array.CreateInstance -Methode erstellt, die einen lengths -Parameter enthält, oder durch Aufrufen der Type.MakeArrayType(Int32) -Methode.

  • Mehrdimensionale Arrays mit vier oder mehr Dimensionen werden nicht unterstützt. Das heißt, der Array.Rank -Eigenschaftswert ist vier oder größer. Verwenden Sie stattdessen verzweigte Arrays (ein Array aus Arrays). array[x,y,z] ist zum Beispiel ungültig, array[x][y][z] aber nicht.

  • Varianz für mehrdimensionale Arrays wird nicht unterstützt und verursacht eine InvalidCastException -Ausnahme zur Laufzeit.

Generics

  • Unendliche generische Typerweiterung führt zu einem Compilerfehler. Dieser Code kann z. B. nicht kompiliert werden:

    class A<T> {}
    
    class B<T> : A<B<A<T>>>
    {}
    

Zeiger

  • Arrays aus Zeigern werden nicht unterstützt.

  • Sie können mithilfe der Reflektion kein Zeigerfeld abrufen oder festlegen.

Serialisierung

Die KnownTypeAttribute(String) -Attribut wird nicht unterstützt. Verwenden Sie stattdessen das KnownTypeAttribute(Type) -Attribut.

Ressourcen

Die Verwendung von lokalisierten Ressourcen mit der EventSource -Klasse wird nicht unterstützt. Die EventSourceAttribute.LocalizationResources -Eigenschaft definiert keine lokalisierten Ressourcen.

Delegaten

Delegate.BeginInvoke und Delegate.EndInvoke werden nicht unterstützt.

Verschiedene APIs

  • Die TypeInfo.GUID-Eigenschaft löst eine Ausnahme aus PlatformNotSupportedException , wenn kein GuidAttribute Attribut auf den Typ angewendet wird. Die GUID wird in erster Linie für die COM-Unterstützung verwendet.

  • Die DateTime.Parse -Methode analysiert Zeichenfolgen, die kurze Datumsangaben in .NET Native enthalten, ordnungsgemäß. Die Kompatibilität mit bestimmten Änderungen bei der Datums- und Uhrzeitanalyse wird jedoch nicht beibehalten.

  • BigInteger.ToString("E")wird in .NET Native ordnungsgemäß gerundet. In einigen Versionen der CLR wird die resultierende Zeichenfolge abgeschnitten und nicht gerundet.

HttpClient-Unterschiede

In .NET Native verwendet die HttpClientHandler Klasse intern WinINet (über die HttpBaseProtocolFilter -Klasse) anstelle der Klassen undWebResponse, die WebRequest in den .NET-Standard-Apps für Windows 8.x-Apps verwendet werden. WinINet unterstützt nicht alle Konfigurationsoptionen, die die HttpClientHandler -Klasse unterstützt. Infolgedessen:

  • Einige der Funktionseigenschaften, die HttpClientHandler auf .NET Native zurückgegeben false werden, während sie in den .NET-Standard-Apps für Windows 8.x-Apps zurückgegeben werdentrue.

  • Einige der Konfigurationseigenschaften-Accessoren get geben immer einen festen Wert auf .NET Native zurück, der sich vom konfigurierbaren Standardwert in .NET für Windows 8.x-Apps unterscheidet.

In den folgenden Abschnitten werden einige zusätzliche Verhaltensunterschiede behandelt.

Proxy

Die HttpBaseProtocolFilter -Klasse unterstützt das Konfigurieren oder Überschreiben des Proxys auf Anforderungsbasis nicht. Dies bedeutet, dass alle Anforderungen auf .NET Native abhängig vom Wert der HttpClientHandler.UseProxy Eigenschaft den systemkonfigurierten Proxyserver oder keinen Proxyserver verwenden. In .NET für Windows 8.x-Apps wird der Proxyserver durch die HttpClientHandler.Proxy -Eigenschaft definiert. Bei .NET Native löst das Festlegen von auf HttpClientHandler.Proxy einen anderen Wert als null eine Ausnahme ausPlatformNotSupportedException. Die HttpClientHandler.SupportsProxy Eigenschaft gibt für .NET Native zurückfalse, während sie in der Standard-.NET Framework für Windows 8.x-Apps zurückgegeben true wird.

Automatische Umleitung

Die HttpBaseProtocolFilter -Klasse lässt nicht zu, dass die maximale Anzahl automatischer Umleitungen konfiguriert wird. Der Wert der HttpClientHandler.MaxAutomaticRedirections Eigenschaft ist in den .NET-Standard-Apps für Windows 8.x-Apps standardmäßig 50 und kann geändert werden. Auf .NET Native ist der Wert dieser Eigenschaft 10. Beim Versuch, sie zu ändern, wird eine PlatformNotSupportedException Ausnahme ausgelöst. Die HttpClientHandler.SupportsRedirectConfiguration Eigenschaft gibt für .NET Native zurückfalse, während sie in .NET für Windows 8.x-Apps zurückgegeben true wird.

Automatische Dekomprimierung

Mit .NET für Windows 8.x-Apps können Sie die HttpClientHandler.AutomaticDecompression Eigenschaft auf Deflate, , GZipsowohl als GZipauch Deflate festlegenNone. .NET Native wird nur zusammen mit GZipoder NoneunterstütztDeflate. Wenn Sie versuchen, die AutomaticDecompression -Eigenschaft im Hintergrund auf Deflate oder GZip festzulegen, wird sie auf Deflate und GZipfestgelegt.

Cookies

Cookieverarbeitung erfolgt gleichzeitig durch HttpClient und WinINet. Cookies aus dem CookieContainer werden mit Cookies im WinINet-Cookiecache kombiniert. Durch das Entfernen eines Cookies aus CookieContainer wird HttpClient am Senden des Cookies gehindert. Wenn der Cookie aber schon von WinINet erkannt wurde und Cookies nicht vom Benutzer gelöscht wurden, wird er durch WinINet gesendet. Es ist nicht möglich, einen Cookie programmgesteuert aus WinINet mithilfe der HttpClient-, HttpClientHandler- oder CookieContainer -API zu entfernen. Durch das Festlegen der HttpClientHandler.UseCookies -Eigenschaft auf false sendet HttpClient keine Cookies mehr; WinINet kann die Cookies immer noch in der Anforderung einschließen.

Anmeldeinformationen

In .NET für Windows 8.x-Apps funktionieren die HttpClientHandler.UseDefaultCredentials Eigenschaften und HttpClientHandler.Credentials unabhängig voneinander. Darüber hinaus akzeptiert die Credentials -Eigenschaft jedes Objekt, das die ICredentials -Schnittstelle implementiert. In .NET Native führt Credentialsnulldas Festlegen der UseDefaultCredentials -Eigenschaft auf zu true . Außerdem kann die Credentials -Eigenschaft nur auf null, DefaultCredentialsoder ein Objekt vom Typ NetworkCredentialfestgelegt werden. Wenn ein beliebiges anderes ICredentials -Objekt, zum Beispiel das sehr beliebte CredentialCache-Objekt, der Credentials -Eigenschaft zugeweisen wird, wird eine PlatformNotSupportedExceptionausgelöst.

Andere nicht unterstützte oder nicht konfigurierbare Features

In .NET Native:

Interop-Unterschiede

Nicht mehr unterstützte APIs

Eine Reihe von selten verwendeten APIs für die Interoperabilität mit verwaltetem Code werden nicht mehr unterstützt. Bei Verwendung mit .NET Native lösen diese APIs möglicherweise eine Ausnahme oder PlatformNotSupportedException eine NotImplementedException Ausnahme aus oder führen zu einem Compilerfehler. In .NET für Windows 8.x-Apps sind diese APIs als veraltet gekennzeichnet, obwohl ihr Aufruf eine Compilerwarnung anstelle eines Compilerfehlers generiert.

Zu den veralteten APIs für VARIANT das Marshallen gehören:

UnmanagedType.Struct wird unterstützt, löst jedoch in einigen Szenarien eine Ausnahme aus, z. B. wenn sie mit IDispatch oder byref Varianten verwendet wird.

Zu den veralteten APIs für IDispatch gehören:

Zu den veralteten APIs für klassische COM-Ereignisse gehören:

Zu den veralteten APIs in der System.Runtime.InteropServices.ICustomQueryInterface Schnittstelle, die in .NET Native nicht unterstützt wird, gehören:

Weitere nicht unterstützte Interopfeatures sind:

Selten verwendete Marshall-APIs:

Plattformaufruf und COM-Interop-Kompatibilität

Die meisten Szenarien für Plattformaufrufe und COM-Interoperabilität werden weiterhin in .NET Native unterstützt. Insbesondere werden die gesamte Interoperabilität mit WinRT-APIs (Windows-Runtime) und das gesamte Marshalling unterstützt, das für Windows-Runtime erforderlich ist. Dazu gehört die Marshallingunterstützung für:

Allerdings unterstützt .NET Native Folgendes nicht:

Das Verwenden von Reflektion zum Aufrufen einer Plattformaufrufmethode wird nicht unterstützt. Sie können diese Einschränkung umgehen, indem Sie den Methodenaufruf in eine andere Methode einschließen und den Wrapper stattdessen mithilfe von Reflektion aufrufen.

Weitere Unterschiede zu .NET-APIs für Windows 8.x-Apps

In diesem Abschnitt werden die verbleibenden APIs aufgelistet, die in .NET Native nicht unterstützt werden. Der größte Satz der nicht unterstützten APIs sind die Windows Communication Foundation (WCF)-APIs.

DataAnnotations (System.ComponentModel.DataAnnotations)

Die Typen in den System.ComponentModel.DataAnnotations Namespaces und System.ComponentModel.DataAnnotations.Schema werden in .NET Native nicht unterstützt. Dazu gehören die folgenden Typen, die in .NET für Windows 8.x-Apps vorhanden sind:

Visual Basic

Visual Basic wird in .NET Native derzeit nicht unterstützt. Die folgenden Typen in den Microsoft.VisualBasic Namespaces und Microsoft.VisualBasic.CompilerServices sind in .NET Native nicht verfügbar:

Reflection Context (System.Reflection.Context-Namespace)

Die System.Reflection.Context.CustomReflectionContext -Klasse wird in .NET Native nicht unterstützt.

RTC (System.Net.Http.Rtc)

Die System.Net.Http.RtcRequestFactory -Klasse wird in .NET Native nicht unterstützt.

Windows Communication Foundation (WCF) (System.ServiceModel.*)

Die Typen in den System.ServiceModel.*-Namespaces werden in .NET Native nicht unterstützt. Dazu gehören die folgenden Typen:

Unterschiede in den Serialisierungsprogrammen

Die folgenden Unterschiede betreffen die Serialisierung und Deserialisierung mit den Klassen DataContractSerializer, DataContractJsonSerializerund XmlSerializer :

Visual Studio-Unterschiede

Ausnahmen und Debuggen

Wenn Sie Apps ausführen, die mithilfe von .NET Native im Debugger kompiliert wurden, werden Ausnahmen mit der ersten Chance für die folgenden Ausnahmetypen aktiviert:

Erstellen von Apps

Verwenden Sie die x86-Buildtools, die standardmäßig von Visual Studio verwendet werden. Sie sollten nicht die AMD64-MSBuild-Tools unter "C:\Program Files (x86)\MSBuild\12.0\bin\amd64" verwenden. Diese können Buildprobleme verursachen.

Profiler

  • Der Visual Studio-CPU-Profiler und der XAML-Arbeitsspeicherprofiler zeigen "Nur mein Code" nicht ordnungsgemäß an.

  • Der XAML-Arbeitsspeicherprofiler zeigt verwaltete Heapdaten nicht ordnungsgemäß an.

  • Der CPU-Profiler identifiziert Module nicht ordnungsgemäß und zeigt Funktionsnamen mit Präfix an.

Komponententest-Bibliotheksprojekte

Das Aktivieren .NET Native für eine Komponententestbibliothek für ein Windows 8.x-App-Projekt wird nicht unterstützt und führt dazu, dass das Projekt nicht erstellt werden kann.

Siehe auch