.NET Native provides static compilation of apps in the Microsoft Store or on the developer's computer. This differs from the dynamic compilation performed for Windows 8.x apps (also previously called Microsoft Store apps) by the just-in-time (JIT) compiler or the Native Image Generator (Ngen.exe) on the device. Despite the differences, .NET Native tries to maintain compatibility with .NET for Windows 8.x apps. For the most part, things that work on the .NET for Windows 8.x apps also work with .NET Native. However, in some cases, you may encounter behavioral changes. This document discusses these differences between the standard .NET for Windows 8.x apps and .NET Native in the following areas:
Exceptions, such as TypeLoadException, that are thrown by the JIT compiler when an app runs on the common language runtime (CLR) generally result in compile-time errors when processed by .NET Native.
Don't call the GC.WaitForPendingFinalizers method from an app's UI thread. This can result in a deadlock on .NET Native.
Don't rely on static class constructor invocation ordering. In .NET Native, the invocation order is different from the order on the standard runtime. (Even with the standard runtime, you shouldn't rely on the order of execution of static class constructors.)
Infinite looping without making a call (for example, while(true);) on any thread may bring the app to a halt. Similarly, large or infinite waits may bring the app to a halt.
Certain generic initialization cycles don't throw exceptions in .NET Native. For example, the following code throws a TypeLoadException exception on the standard CLR. In .NET Native, it doesn't.
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 some cases, .NET Native provides different implementations of .NET Framework class libraries. An object returned from a method will always implement the members of the returned type. However, since its backing implementation is different, you may not be able to cast it to the same set of types as you could on other .NET Framework platforms. For example, in some cases, you may not be able to cast the IEnumerable<T> interface object returned by methods such as TypeInfo.DeclaredMembers or TypeInfo.DeclaredProperties to T[].
The WinInet cache isn't enabled by default on .NET for Windows 8.x apps, but it is on .NET Native. This improves performance but has working set implications. No developer action is necessary.
Dynamic programming differences
.NET Native statically links in code from .NET Framework to make the code app-local for maximum performance. However, binary sizes have to remain small, so the entire .NET Framework can't be brought in. The .NET Native compiler resolves this limitation by using a dependency reducer that removes references to unused code. However, .NET Native might not maintain or generate some type information and code when that information can't be inferred statically at compile time, but instead is retrieved dynamically at runtime.
.NET Native does enable reflection and dynamic programming. However, not all types can be marked for reflection, because this would make the generated code size too large (especially because reflecting on public APIs in .NET Framework is supported). The .NET Native compiler makes smart choices about which types should support reflection, and it keeps the metadata and generates code only for those types.
For example, data binding requires an app to be able to map property names to functions. In .NET for Windows 8.x apps, the common language runtime automatically uses reflection to provide this capability for managed types and publicly available native types. In .NET Native, the compiler automatically includes metadata for types to which you bind data.
The .NET Native compiler can also handle commonly used generic types such as List<T> and Dictionary<TKey,TValue>, which work without requiring any hints or directives. The dynamic keyword is also supported within certain limits.
Note
You should test all dynamic code paths thoroughly when porting your app to .NET Native.
The default configuration for .NET Native is sufficient for most developers, but some developers might want to fine- tune their configurations by using a runtime directives (.rd.xml) file. In addition, in some cases, the .NET Native compiler is unable to determine which metadata must be available for reflection and relies on hints, particularly in the following cases:
Because the compiler can't determine the instantiations, a generic type that you want to reflect on has to be specified by runtime directives. This isn't just because all code must be included, but because reflection on generic types can form an infinite cycle (for example, when a generic method is invoked on a generic type).
.NET Native also includes profiling tools that help the developer determine which types outside the default set should support reflection.
Other reflection-related differences
There are a number of other individual reflection-related differences in behavior between .NET for Windows 8.x apps and .NET Native.
In .NET Native:
Private reflection over types and members in the .NET Framework class library is not supported. You can, however, reflect over your own private types and members, as well as types and members in third-party libraries.
The ParameterInfo.HasDefaultValue property correctly returns false for a ParameterInfo object that represents a return value. In .NET for Windows 8.x apps, it returns true. Intermediate language (IL) doesn't support this directly, and interpretation is left to the language.
Public members on the RuntimeFieldHandle and RuntimeMethodHandle structures aren't supported. These types are supported only for LINQ, expression trees, and static array initialization.
Binary serialization of exceptions is generally not supported. As a result, non-serializable objects can be added to the Exception.Data dictionary.
Unsupported scenarios and APIs
The following sections list unsupported scenarios and APIs for general development, interop, and technologies such as HTTPClient and Windows Communication Foundation (WCF):
If you override the ValueType.Equals and ValueType.GetHashCode methods for a value type, don't call the base class implementations. In .NET for Windows 8.x apps, these methods rely on reflection. At compile time, .NET Native generates an implementation that doesn't rely on runtime reflection. This means that if you don't override these two methods, they will work as expected, because .NET Native generates the implementation at compile time. However, overriding these methods but calling the base class implementation results in an exception.
Value types larger than 1 megabyte aren't supported.
Value types can't have a parameterless constructor in .NET Native. (C# and Visual Basic prohibit parameterless constructors on value types. However, these can be created in IL.)
Dynamic creation of multidimensional arrays isn't supported. Such arrays are typically created by calling an overload of the Array.CreateInstance method that includes a lengths parameter, or by calling the Type.MakeArrayType(Int32) method.
Multidimensional arrays that have four or more dimensions aren't supported; that is, their Array.Rank property value is four or greater. Use jagged arrays (an array of arrays) instead. For example, array[x,y,z] is invalid, but array[x][y][z] isn't.
Variance for multidimensional arrays isn't supported and causes an InvalidCastException exception at run time.
Generics
Infinite generic type expansion results in a compiler error. For example, this code fails to compile:
class A<T> {}
class B<T> : A<B<A<T>>>
{}
Pointers
Arrays of pointers aren't supported.
You can't use reflection to get or set a pointer field.
The DateTime.Parse method correctly parses strings that contain short dates in .NET Native. However, it doesn't maintain compatibility with certain changes in date and time parsing.
BigInteger.ToString("E") is correctly rounded in .NET Native. In some versions of the CLR, the result string is truncated instead of rounded.
HttpClient differences
In .NET Native, the HttpClientHandler class internally uses WinINet (through the HttpBaseProtocolFilter class) instead of the WebRequest and WebResponse classes used in the standard .NET for Windows 8.x apps. WinINet doesn't support all the configuration options that the HttpClientHandler class supports. As a result:
Some of the capability properties on HttpClientHandler return false on .NET Native, whereas they return true in the standard .NET for Windows 8.x apps.
Some of the configuration property get accessors always return a fixed value on .NET Native that is different than the default configurable value in .NET for Windows 8.x apps.
Some additional behavior differences are covered in the following subsections.
Proxy
The HttpBaseProtocolFilter class doesn't support configuring or overriding the proxy on a per-request basis. This means that all requests on .NET Native use the system-configured proxy server or no proxy server, depending on the value of the HttpClientHandler.UseProxy property. In .NET for Windows 8.x apps, the proxy server is defined by the HttpClientHandler.Proxy property. On .NET Native, setting the HttpClientHandler.Proxy to a value other than null throws a PlatformNotSupportedException exception. The HttpClientHandler.SupportsProxy property returns false on .NET Native, whereas it returns true in the standard .NET Framework for Windows 8.x apps.
Cookie handling is performed simultaneously by HttpClient and WinINet. Cookies from the CookieContainer are combined with cookies in the WinINet cookie cache. Removing a cookie from CookieContainer prevents HttpClient from sending the cookie, but if the cookie was already seen by WinINet, and cookies weren't deleted by the user, WinINet sends it. It isn't possible to programmatically remove a cookie from WinINet by using the HttpClient, HttpClientHandler, or CookieContainer API. Setting the HttpClientHandler.UseCookies property to false causes only HttpClient to stop sending cookies; WinINet might still include its cookies in the request.
The SetCookie2 header in responses is ignored as obsolete.
Interop differences
Deprecated APIs
A number of infrequently used APIs for interoperability with managed code have been deprecated. When used with .NET Native, these APIs may throw a NotImplementedException or PlatformNotSupportedException exception, or result in a compiler error. In .NET for Windows 8.x apps, these APIs are marked as obsolete, although calling them generates a compiler warning rather than a compiler error.
Most platform invoke and COM interop scenarios are still supported in .NET Native. In particular, all interoperability with Windows Runtime (WinRT) APIs and all marshaling required for the Windows Runtime is supported. This includes marshaling support for:
Using reflection to invoke a platform invoke method isn't supported. You can work around this limitation by wrapping the method call in another method and using reflection to call the wrapper instead.
Other differences from .NET APIs for Windows 8.x apps
This section lists the remaining APIs that aren't supported in .NET Native. The largest set of the unsupported APIs is the Windows Communication Foundation (WCF) APIs.
In .NET Native, DataContractSerializer and DataContractJsonSerializer fail to serialize or deserialize a derived class that has a base class member whose type isn't a root serialization type. For example, in the following code, trying to serialize or deserialize Y results in an error:
using System;
public class InnerType{}
public class X
{
public InnerType instance { get; set; }
}
public class Y : X {}
Type InnerType isn't known to the serializer, because the members of the base class aren't traversed during serialization.
XmlSerializer doesn't honor the IXmlSerializable custom serialization interface. If you have a class that implements this interface, XmlSerializer considers the type a plain old CLR object (POCO) type and serializes only its public properties.
Use the x86 build tools that are used by default by Visual Studio. We don't recommend using the AMD64 MSBuild tools, which are found in C:\Program Files (x86)\MSBuild\12.0\bin\amd64; these may create build problems.
Profilers
The Visual Studio CPU Profiler and XAML Memory Profiler don't display Just-My-Code correctly.
The XAML Memory Profiler doesn't accurately display managed heap data.
The CPU Profiler doesn't correctly identify modules, and displays prefixed function names.
Unit Test Library projects
Enabling .NET Native on a Unit Test Library for a Windows 8.x app project isn't supported and causes the project to fail to build.
Microservice applications, because of their distributed nature, can be difficult to secure. In this module, you'll learn how to classify sensitive data in a cloud-native application, redact sensitive data in log files, and generate compliance reports for a cloud-native application.