App platform compatibility for Windows Phone 8
[ This article is for Windows Phone 8 developers. If you’re developing for Windows 10, see the latest documentation. ]
In general, the Windows Phone app platform enables apps that target Windows Phone OS 7.1 to run without modification or recompilation on Windows Phone 8. However, you should test your apps on the Windows Phone 8 emulator or on a device to make sure the apps perform as expected. The performance improvements; faster, multicore hardware support; and cosmetic differences featured in Windows Phone 8 could affect the behavior and appearance of your Windows Phone OS 7.1 app on Windows Phone 8.
In addition, there are other scenarios in which a Windows Phone OS 7.1 app may behave differently when it runs on Windows Phone 8. One scenario would be a result of source incompatibility and an applied quirks mode change. The cause of the other scenario is binary incompatibility, otherwise known as a breaking change. For the most part, because of quirks mode, source incompatibility differences are transparent to developers who target a specific version of Windows Phone. However, you may see app compatibility issues due to changes in runtime behavior, changes in what is considered a breaking change, or changes that occur when you recompile your Windows Phone OS 7.1 app for Windows Phone 8, and then quirks mode no longer applies. This topic discussed quirks and breaking changes in more detail, and lists the known breaking changes and quirks in Windows Phone 8 that affect developers.
Note
In this article, references to Windows Phone OS 7.1 also pertain to Windows Phone OS 7.0.
This topic contains the following sections.
- Definition of a quirk
- Definition of a breaking change
- Breaking changes in Windows Phone 8
- Quirks mode behavior in the .NET Framework
Definition of a quirk
Windows Phone 8 introduces feature improvements or behavior changes that may cause incompatibility issues for existing apps. For some features and APIs, rather than introducing a breaking change, the Windows Phone app platform provides a quirks mode that preserves the legacy behavior and applies it where appropriate, depending on the version of the Windows Phone the app was originally built and tested for. If the target version is Windows Phone OS 7.1, quirks mode either emulates the same behavior, or it uses the same code as Windows Phone OS 7.1. In other words, the app runs in Windows Phone 8 as it did when it was tested against the runtime it originally targeted.
Note
A third-party library that is developed for Windows Phone OS 7.1 takes advantage of quirks if it is used in a Windows Phone OS 7.1 app. However, if the library is used in a Windows Phone 8 app, it runs outside of quirks mode.
If the source code for an app that targets Windows Phone OS 7.1 is recompiled to target Windows Phone 8, quirks mode is no longer in effect. Because the app now targets Windows Phone 8, it executes the new code in all cases. Quirks mode is not an opt-in or configurable feature—it is applied automatically depending on an app's target platform.
Definition of a breaking change
For a binary incompatibility or breaking change, when an app that targets Windows Phone OS 7.1 is run on Windows Phone 8, it doesn’t operate the same because of a difference in runtime behavior. These differences in behavior are not quirked, which means you will need to modify your app for it to run the same on both platforms. For example, these changes could be small differences in the app appearance or they could be differences in the order that the code executes.
Breaking changes in Windows Phone 8
The following tables list breaking changes between the Windows Phone OS 7.1 and Windows Phone 8 platforms that are not affected by quirks mode. Some of these changes may require modification to your apps so that they run the same on Windows Phone OS 7.1 and Windows Phone 8. For info about the effect of the change and how your source code should be modified, see the Impact column of the tables.
Because of many changes in Windows Phone 8, you may encounter some issues while upgrading your project. For more info about steps you need to take and issues you may encounter when upgrading your projects, see How to upgrade an app project to Windows Phone 8.
Windows Phone-specific features
The following table lists breaking changes in core Windows Phone features.
Feature |
Change |
Impact/Workaround |
---|---|---|
Back button navigation |
When the user clicks an ad displayed in an app and clicks the back button twice in quick succession, the app exits in Windows Phone 8. In Windows Phone OS 7.1, the user would navigate through the apps back stack. |
This is a change in UI behavior and a workaround is not available. However, you must ensure that your app tombstones properly in case the user exits the app unexpectedly. |
Background file transfer |
The limit on the number of concurrent file transfers has increased from 5 to 25. |
An exception doesn’t occur until the limit of 25 is reached. You don’t need to remove requests until the higher limit is reached. |
Background file transfer |
In Windows Phone 8, the background transfer service will transfer on the following data networks while the app is in the foreground. In Windows Phone OS 7.0, transfers do not occur on these data networks, regardless of whether the app is running in the foreground.
In Windows Phone 8, transfers won’t proceed on these networks while the app is not in the foreground. This limitation is shared by the HttpWebRequest object, so performing your own transfer doesn’t provide any advantages over using background transfers. On networks that are 3G and higher, background transfers will proceed on both Windows Phone 8 or Windows Phone OS 7.1, regardless of whether the app is running in the foreground, assuming all other conditions are met. |
Background transfers will occur in Windows Phone 8 that did not occur in Windows Phone OS 7.1. You should account for that in your code if you plan to target both platforms. |
Choosers |
Previously, calling a Chooser's Show method while navigation to the Chooser was already taking place would throw an exception. Now, the second call to Show fails silently. |
You don’t need to place calls to a Chooser’s Show method in a try block. |
The TrueHeading and MagneticHeading properties of the CompassReading structure return values of type double. In Windows Phone OS 7.1, these double values are returned without precision; for example, as 122.0 degrees. In Windows Phone 8, the double values of these properties are returned with precision; for example, as 122.12345 degrees. |
Ensure that you are not truncating the precision from these values when manipulating or converting them; for example, if you convert them to strings and then convert them back to double values. |
|
Digital Rights Management (DRM) |
In Windows Phone 8, an app cannot properly consume DRM video as a texture; the video defaults to a black display. In Windows Phone OS 7.1 and earlier versions, DRM protected video is accessible as a texture for composition. The video is composed like any other texture content in the scene. The standard video overlay controls are not affected. The compositor blends those frames correctly. |
The only way to show a frame is by passing it to the compositor for drawing as an overlay surface. In each of the following cases, the video cannot be rendered via the overlay.
|
FM Radio |
Windows Phone 8 does not support the FM radio feature. If you use the FM radio API in a Windows Phone 8 app, a RadioDisabledException will occur. |
If your app calls the FM radio API, detect the OS version of the phone that is running the app, and then disable this part of your app if the device is a Windows Phone 8 phone. Otherwise, an exception occurs, and if your app fails to handle the exception, the app exits unexpectedly. |
LayoutUpdated event |
Event ordering is not exactly the same between Windows Phone OS 7.1 and Windows Phone 8. Because of this, the initial LayoutUpdated event does not have the correct dimensions the first time that it is raised on Windows Phone 8. The second time it is raised, the dimensions are correct. |
If you use the dimensions in LayoutUpdated, you can work around this difference by first checking that ActualWidth and ActualHeight are greater than 0 and valid. For some example code that handles this difference, see the LayoutUpdated event. |
ListBox control |
The ListBox control does not display in the Toolbox if you are working in a Windows Phone 8 project. The LongListSelector control is the recommended control for displaying lists of items in Windows Phone 8 apps. |
You can manually add the ListBox control in the XAML editor, or use the LongListSelector control. |
Local database |
In Windows Phone 8, you can no longer access a local database in isolated storage using a read-only connection string, unless you are accessing the installation folder. |
If you try to access a local database in isolated storage using a read-only connection string, a NotSupportedException occurs. |
ManipulationCompleted event |
In Windows Phone 8, if you try to handle the ManipulationCompleted event for the LongListSelector, Panorama, or Pivot controls, the event handler code does not run. In Windows Phone OS 7.1, the event handler code does run. |
In Windows Phone 8, LongListSelector, Panorama, and Pivot are part of the framework. The ManipulationCompleted event is marked as handled in Windows Phone 8 to make the UI more responsive. If you need to handle the ManipulationCompleted event in Windows Phone 8 and Windows Phone OS 7.1, use the AddHandler method. For more information, see the ManipulationCompleted event. |
If you call Show(String) method from the app Activated and Launching event handlers an InvalidOperationException is thrown with the message Error Displaying MessageBox. |
Call the Show(String) method from the OnNavigatedTo(NavigationEventArgs) method. |
|
In Windows Phone 8, if you call Show in OnBackKeyPress(CancelEventArgs) or a handler for the BackKeyPress event, the app will exit. |
You can work around this by calling Show on a different thread, as described in the following steps.
|
|
MessageBox control |
Spacing, margin, and padding in the MessageBox control was updated for Windows Phone 8. |
The changes in spacing, margin, and padding could affect the layout of the control in your app. Test your Windows Phone OS 7.1 apps that use the MessageBox control on Windows Phone 8 to make sure that their appearance is unchanged. |
Microsoft.Phone.Media.Extended assembly |
The Microsoft.Phone.Media.Extended assembly that shipped in-ROM on Windows Phone OS 7.1 phone devices is not available on a Windows Phone 8 phone. |
If you were using reflection to access the API in this assembly, because they were not publicly exposed, your app may fail on a Windows Phone 8 device. Remove the calls to this assembly and use the publicly exposed media API |
Networking |
In Windows Phone 8, because the Windows Phone 8 client can handle the Vary header and cache responses, a Web service call may complete much faster than in previous versions. |
This change should have minimal impact. However, if you are making a web service call your code must not rely on the download taking more than 1 second. You should use milliseconds and a floating point number when checking the response time, because it could be less than 1 second. |
Panel controls |
In Windows Phone 8, when a control that derives from Panel (such as Canvas, GridLength, or StackPanel) has a height that is greater than 2560, the Background brush is set to black, even if the background is set to a different color. |
There is no workaround for this issue. |
Photo chooser task |
In Windows Phone 8, the photo chooser task creates a directory in the top level of the app’s isolated storage called “PlatformData”. |
If an app that targets Windows Phone OS 7.1 is deployed to a phone that is running Windows Phone 8, or you create a new app that targets Windows Phone 8 and that app uses the photo chooser task, if your app iterates over the contents of isolated storage and you want to skip over directories created by the system, skip over “PlatformData” and “Shared”. |
ProgressIndicator in the system tray |
In Windows Phone OS 7.1, the code to update the progress indicator in the system tray is synchronous. In Windows Phone 8, the code to update the progress indicator is now asynchronous. In some cases, this change can cause no progress indicator to display in the system tray in Windows Phone 8. For example, if you use the ProgressIndicator class to set the progress indicator and immediately block the UI thread (such as, by doing resource-intensive work), then the progress indicator will not be displayed. This is because the system hasn't been able to handle the request to update the progress indicator. |
There is a potential workaround for this issue. If you use a timer with a small timeout and an infinite period, and then call Dispatcher..::.BeginInvoke within the timer callback to schedule the resource-intensive work, this will enable the message queue to be processed and allow the progress indicator update to take effect before starting the resource-intensive work. |
Secure Sockets Layer (SSL) |
When your app makes an SSL request to a web service or web site, apps that target Windows Phone 8 contact the issuer of the site's certificate for the security certificate revocation list. This additional network request in Windows Phone 8 apps increases the time required for the SSL request. If the certificate revocation list is not received in a timely manner, the SSL request may time out, especially over a slow or unreliable network connection. |
Make sure that your app handles the possibility of a timeout and retries the request or continues without the requested data. |
Slider control |
In Windows Phone 8, the Slider control and its API have changed significantly. HorizontalLargeIncrease, HorizontalLargeDecrease, HorizontalThumb, VerticalLargeIncrease, VerticalLargeDecrease, and VerticalThumb have been removed from the control template. The corresponding new template parts are HorizontalFill, HorizontalTrack, and HorizontalCenterElement, VerticalFill, VerticalTrack, and VerticalCenterElement. The new template parts are all of type FrameworkElement. |
If you have retemplated the Slider control in an app that you are upgrading to Windows Phone 8, you may have to modify your control template to accommodate the template parts that have been removed or added. |
TextBox control |
In Windows Phone 8, events raised by the Enter key in a TextBox when the value of its AcceptsReturn property is false (that is, when the TextBox is not a multi-line TextBox) behave differently. In apps that target Windows Phone OS 7.1, the TextInput event is raised for Enter key presses that are not handled by the TextBox. In apps that target Windows Phone 8, the TextInput event is not raised for these Enter key presses. |
In apps that target Windows Phone 8, handle the KeyDown event to capture Enter key presses that are not handled by TextBox. |
Tiles |
In Windows Phone 8, creating a Tile by using the Create(Uri, ShellTileData) method inside the Closing handler will throw an InvalidOperationException. |
Use the Create(Uri, ShellTileData) method in another location in your app project. |
UIElement text input events |
The TextInput, TextInputStart, and TextInputUpdate events do not occur in Windows Phone 8 and they did occur in Windows Phone OS 7.1. |
You can’t rely on text input events to detect changes in a text control. Instead, use the KeyDown event to detect text changes. |
VibrateController controller |
In Windows Phone OS 7.1, if you called the Stop()()() method of the VibrateController without previously calling its Start(TimeSpan) method, all vibrations were canceled, including those started by other apps such as the phone or a toast notification. In Windows Phone 8, if you call the Stop()()() method of the VibrateController without previously calling its Start(TimeSpan) method, nothing happens. No exception is raised. |
There is no workaround required for this issue. |
Video play back |
On Windows Phone 8, resuming video play back after locking and then unlocking the phone has changed. On Windows Phone OS 7.1, the video opens in the paused state and the image is visible. On Windows Phone 8, the video opens in the paused state but an empty black box is displayed in place of a frame from the paused video. In both cases, the user has to click Play to resume the video. |
This issue is a change in the UI experience and there is no workaround. |
WebBrowser control |
The UserAgent string associated with the web browser control has changed slightly between Windows Phone OS 7.1 and Windows Phone 8. |
Don’t look for an exact match of a UserAgent string, but instead look for a general match. |
WebBrowser control |
The WebBrowser control has several changes that affect how content displays in an app. If your app uses the WebBrowser control, it may not display the same in Windows Phone 8 as it does on Windows Phone OS 7.1. |
You should deploy and test your app on the Windows Phone 8 emulator and on the device. You should look for changes in appearance to the text, bullet items, and drop-down arrows in the WebBrowser, and then determine if these changes affect the usability of your app. |
WebBrowser control |
The WebBrowser control may behave differently when scrolling. If your app uses the WebBrowser control, it may not have the same scrolling behavior in Windows Phone 8 as it does on Windows Phone OS 7.1. |
You should test scrolling in the WebBrowser and determine if any differences affect the usability of your app. |
WebBrowser control |
If content displayed in the WebBrowser control uses page scale viewport settings (for example, <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"/>), the layout may be different. In Windows Phone OS 7.1, the WebBrowser control does not account for the page scale viewport settings when rendering the layout. In Windows Phone 8, the WebBrowser control does use the page scale viewport settings when rendering the layout. |
If you specify page scale viewport settings, you should test your app for layout differences. |
WebBrowser control |
Using the ScriptNotify method of the Window.External object to call OnContextMenu is not supported in Windows Phone 8. |
You can use the OnMSGestureHold event to show a context menu in Windows Phone 8. |
WebBrowser control |
In Windows Phone 8, a blinking cursor does not always appear in text fields. |
There is no workaround. The text field works as expected. |
XNA |
Due to changes in when the Game.IsActive property is set, a game may not resume as expected. |
Test your Windows Phone app on Windows Phone 8 by running the game, locking the device while the game is running, and then unlocking the device to see if the device resumes correctly. If it doesn’t, adjust where you check the Game.IsActive property before pausing the game. |
XNA |
In Windows Phone 8, the following render formats are not supported.
|
If you use these formats, they will default to SurfaceFormat.Color. |
XNA TouchPanel |
In Windows Phone OS 7.1 apps, the TouchPanel APIs return size information that represent physical pixels. In Windows Phone 8 apps, the TouchPanel APIs return size information that represent logical pixels. This is because Windows Phone 8 now supports multiple resolutions. |
You should test your app at different resolutions to ensure that size, position, and hit targets work as expected. |
The common language runtime
The following table lists app compatibility issues in the common language runtime between the Windows Phone OS 7.1 and Windows Phone 8 platforms.
Feature |
Change |
Impact/Workaround |
---|---|---|
Finalization |
Windows Phone 8 includes a completely different garbage collector than Windows Phone OS 7.1. |
Code that relies on a particular order of object finalization may be broken. The dependency on a particular order of finalization should be removed. In addition, code in user-defined finalizers should not make calls to managed data members. |
Floating-point comparisons |
Because of differences in rounding behavior in Windows Phone OS 7.1 and Windows Phone 8, floating point values may differ. This is especially true when performing equality comparisons with a constant and the result of a floating point computation. |
Direct comparisons with floating point computations are generally not recommended. |
Support for loading multi-module assemblies |
In Windows Phone OS 7.1, the common language runtime loads multi-module assemblies; in Windows Phone 8, it does not. |
Multi-module assemblies are managed assemblies that are stored in multiple files. This change poses very few compatibility issues, because the multi-module assemblies are used extremely rarely. Note that multi-module assemblies are not .NET module files compiled into a single assembly. |
Support for adding mixed-mode assemblies (assemblies that target the desktop version of the .NET Framework) |
In Windows Phone OS 7.1, apps with mixed-mode binaries that are not loaded execute successfully; in Windows Phone 8, they do not. |
To run successfully under Windows Phone 8, the mixed-mode binaries must be removed from the app. |
Threading (the .NET thread pool, .NET thread scheduling policy, operating system scheduling policy) |
In Windows Phone OS 7.1, apps run on a single core, and the scheduler is less aggressive in time-slicing threads in the single core. In Windows Phone 8, applications can run on multiple cores and the scheduler is more aggressive in time-slicing threads. |
Race conditions and other concurrency bugs are more likely to occur in Windows Phone 8 than Windows Phone OS 7.1. To address this issue, developers must write correct multithreaded code. |
Common Intermediate Language (CIL) method size |
In Windows Phone 8, there is a 256-KB limit on the size of a method's CIL. |
App installation that succeeded under Windows Phone OS 7.1 may fail under Windows Phone 8. This should affect an extremely small number of apps. |
Access to private nested classes |
Windows Phone OS 7.1 allows a class to access its private nested classes; Windows Phone 8 does not. |
Access to private nested classes is unsupported. |
Any inlineable, sealed instance method that doesn't access the this pointer in its method body but only calls static members. |
The method call throws a NullReferenceException in Windows Phone 8 . In Windows Phone OS 7.1, the static methods may be called at runtime, but in a managed debugger a NullReferenceException is thrown. |
This behavior conforms to the CLI specification. The NullReferenceException that results from calling a method on a null reference should be handled, or instance methods should not be invoked on null objects. |
Instance field reads and writes |
Instance field reads are optimized by the JIT compiler. |
Applications that write to and read from an instance field on separate threads may experience failure. Such fields should be marked with the C# volatile keyword. |
The .NET Framework class library
The following table lists app compatibility issues in the .NET Framework class library between the Windows Phone OS 7.1 and Windows Phone 8 platforms.
Feature |
Change |
Impact/Workaround |
---|---|---|
If the dimension parameter is equal to Array..::.Rank, Windows Phone OS 7.1 returns 0, and Windows Phone 8 throws an IndexOutOfRangeException exception. |
An IndexOutOfRangeException is the documented behavior. Any app that depends on the Windows Phone OS 7.1 behavior must handle the exception. |
|
Conversion of Double..::.NaN or Single..::.NaN to an integer |
The resulting integer value differs on Windows Phone OS 7.1 and Windows Phone 8. |
According to the CLI specification, the result of the conversion is unspecified. |
After putting a monitor lock on an instance field, user code replaces the field with a new value. Depending on timing, when another thread tries to lock on or pulse the field, this other thread may be working on an object which it has not put a lock on. |
Incorrect use of these methods can lead to deadlock, exception, or inconsistent state modification. To work around the issue, use a different object to synchronize. |
|
Type..::.BaseType property |
In Windows Phone OS 7.1, the property returns the generic type definition. In Windows Phone 8, it reflects the generic type arguments. |
This change should have minimal impact. |
Type..::.GetMember method |
To return the constructor, Windows Phone OS 7.1 expects the string parameter to be the same as the class name. Windows Phone 8 expects it to be ".ctor". |
This change should have minimal impact. |
Type..::.GetType method |
If the type name contains invalid characters, Windows Phone OS 7.1 throws a TypeLoadException exception, whereas Windows Phone 8 throws an ArgumentException exception. |
This change should have minimal impact. |
Environment..::.SpecialFolder..::.Favorites enumeration member |
The value of this enumeration member is 22 in Windows Phone OS 7.1 and 6 in Windows Phone 8. |
Because user code cannot call a method that expects this argument, this change should have no impact. |
IsolatedStorageFile filenames and IsolatedStorageFile..::.GetFileNames method |
In Windows Phone OS 7.1, a filename can end with a dot ("."), and GetFileNames("*.") retrieves only files whose names end with a dot. In Windows Phone 8, these operations throw an exception. |
Rename files so that they do not end with a dot. Call GetFiles("*") to retrieve all files. |
The order of files in the returned array may differ in Windows Phone OS 7.1 and Windows Phone 8. |
Apps that depend on a particular order may be broken. Note that file system ordering is never guaranteed. |
|
IsolatedStorageFileStream with a stream opened with FileShare..::.None. |
Because of differences in garbage collection, code in Windows Phone OS 7.1 that did not call Dispose on the stream before releasing all its strong references will not be garbage collected and finalized in a timely manner. As a result, other streams may not be opened against that file. |
Applications should use a using statement to ensure that the object is properly disposed. |
System.Reflection.Emit.ILGenerator.syncObj field |
In Windows Phone OS 7.1, syncObj is a protected internal field. The field is not present in Windows Phone 8. |
This change should have no impact. |
Mutex class |
In Windows Phone OS 7.1, if one process exits while holding a shared mutex, another process can then acquire that mutex, in Windows Phone 8, an exception is thrown. |
This change should have minimal impact. To work around the change, the first process cannot abandon the mutex, or the exception that is thrown when the second process attempts to acquire the mutex can be handled. |
ParameterBuilder..::.SetCustomAttribute(ConstructorInfo, array<Byte>[]()[]) method |
The method is not available to user code in Windows Phone 8. |
This change should have minimal impact. In Windows Phone OS 7.1, the attribute is available only through the DynamicMethod class, which makes the attribute of limited utility. |
Precision of computations with Single. |
Windows Phone OS 7.1 uses higher double precision for intermediate results of complex float computations. Windows Phone 8 on ARM systems uses lower float precision. |
In some cases, floating point computations with Single values can produce different results on Windows Phone OS 7.1 and Windows Phone 8. If this is the case, explicitly cast to a Double before performing the computation. |
Referer header value set by a BitmapImage request from a URI |
In Windows Phone OS 7.1, the value of the Referer header set by a BitmapImage request from a URI references the installation directory of the app in the format file:///Applications/Install/<GUID>/Install/. In versions of Windows Phone released before Windows Phone 8 (8.0.10322.0), the value of the Referer header references the installation directory of the app in a different format. This occurs for apps that target both Windows Phone OS 7.1 and Windows Phone 8. This issue has been resolved in Windows Phone 8 (8.0.10322.0).
|
Applications that rely on the value of the Referer header may be broken. To work around this issue, specify a custom value for the Referer header. For one possible solution, see WP7 Mango: Image Download With Custom Referer Header. |
Windows Phone OS 7.1 and Windows Phone 8 return different hash codes for the same string. |
Applications that rely on a particular string having a particular hash code will be broken. |
|
The order of properties in the returned PropertyInfo array is different. |
Code that depends on a fixed order of elements in the array, such as serialization code, may break the application. The developer should remove the dependency on property ordering. |
|
WaitHandle..::.WaitAll method |
The method is support in Windows Phone 8 but throws a NotSupportedException exception in Windows Phone OS 7.1. |
This change has an impact in the unlikely event that app code is dependent on handling the NotSupportedException exception. |
The XmlSerializer class has different rules regarding what input is valid in Windows Phone OS 7.1 and Windows Phone 8. Some of these differences are quirked; see Quirks mode behavior in the .NET Framework. |
To use XmlSerializer with source code recompiled to target Windows Phone 8:
|
|
If the textReader argument is null, the method throws an ArgumentNullException exception in Windows Phone 8 and an InvalidOperationException in Windows Phone OS 7.1. |
The ArgumentNullException exception must be handled if null is passed to the method. |
|
XmlSerializer..::.Serialize(TextWriter, Object) and XmlSerializer..::.Serialize(TextWriter, Object, XmlSerializerNamespaces) |
If the textWriter argument is null, the method throws an ArgumentNullException exception in Windows Phone 8 and a NullReferenceException in Windows Phone OS 7.1. |
The ArgumentNullException exception must be handled if null is passed to the method. |
Quirks mode behavior in the .NET Framework
The following sections list quirks mode behavior for common language runtime features and in the .NET Framework for Windows Phone.
The common language runtime
The following table lists quirks mode behavior in the common language runtime.
Feature or area |
Windows Phone 8 behavior |
Quirks mode behavior |
---|---|---|
Assembly binding: cultures |
The binder checks to ensure that the app assembly has a neutral culture. |
The binder can bind to an assembly that has culture-specific resources. |
Assembly binding: version numbers |
Unsigned assemblies use version numbers for assembly binding. |
Version numbers are ignored. |
Just-in-time (JIT) inlining |
The JIT compiler follows a set of rules for inlining that are unique to Windows Phone 8. |
The JIT compiler follows the set of rules used by Windows Phone OS 7.1. |
Memory allocation for per-class static data |
There is no limit on the total size of static data per class. |
The runtime throws a TypeInitializationException exception if the size of static data for a class exceeds 64K. |
Runtime loader behavior: overlapping fields of value types that have differing visibility |
If overlapping fields of value types have differing visibility, the loader throws a TypeLoadException exception. |
The loader allows overlapping fields of value types to have differing visibility. |
Runtime loader behavior: x86-specific images |
x86-specific Common Intermediate Language (CIL) images cannot be loaded on ARM systems. |
x86-specific CIL images can be loaded on ARM systems. |
Runtime loader behavior: uniqueness of type definitions |
Duplicate type definitions are not allowed. To recompile and execute Windows Phone OS 7.1 code successfully, either change obfuscators or do not use obfuscated code. |
Duplicate type definitions that are produced by an obfuscator can be iterated. |
Runtime loader behavior: invalid custom attributes on static fields |
The runtime throws a BadImageFormatException. |
Ignore the invalid attribute. |
Static constructors that have the TypeAttributes..::.BeforeFieldInit flag |
The constructor is run lazily. |
The constructor is not run lazily. |
The .NET Framework class library
The following table lists quirks mode behavior for the types and members of the .NET Framework class library.
Type or member |
Windows Phone 8 behavior |
Windows Phone OS 7.1 quirks mode behavior |
---|---|---|
Passing an array type to the Activator..::.CreateInstance method |
The method throws a MissingMethodException exception. |
The method returns an array whose length is zero. |
Array..::.BinarySearch<(Of <(T>)>)(array<T>[]()[], T), Array..::.Sort<(Of <(T>)>)(array<T>[]()[]), Array..::.Sort<(Of <(TKey, TValue>)>)(array<TKey>[]()[], array<TValue>[]()[], Int32, Int32, IComparer<(Of <(TKey>)>)) |
Uses a sorting algorithm unique to Windows Phone 8. |
Uses a sorting algorithm unique to Windows Phone OS 7.1. |
Assembly..::.FullName property |
For null names, the property returns String..::.Empty. |
The property returns the fully qualified type name ("System.Reflection.AssemblyName"). |
Assembly..::.GetType method |
The method searches for the specified type only in the assembly on which it is called. |
The method searches for the specified type in mscorlib.dll as well as in the assembly on which it is called. |
Assembly..::.GetType and Module..::.GetType methods |
The type name cannot include the fully qualified assembly name. |
The type name can include the fully qualified assembly name. |
Load method |
Special characters in assembly names, including apostrophes ('), quotation marks ("), commas (,), and equals signs (=) must be escaped. Otherwise, the assembly cannot be loaded and an exception is thrown. |
Unescaped special characters are allowed in assembly names. |
The qualified name of an assembly name cannot begin with "+". |
The qualified name of an assembly can begin with "+". |
|
For assemblies that have no public key, the method returns null. |
The method returns Byte[0]. |
|
Comparison operations, such as a call to the Array..::.Sort method, for a derived class that implements IComparable and whose base class implements IComparable<(Of <(T>)>), where T is the base class |
The base class CompareTo(T) implementation is called. |
The derived class CompareTo(Object) implementation is called. |
Calls to Attribute..::.GetCustomAttribute(MemberInfo, Type, Boolean) and Attribute..::.GetCustomAttributes(MemberInfo, Boolean) with an element argument of type PropertyInfo and an inherit argument equal to true |
The method searches the both public and non-public parent properties for attributes. |
The method searches only public parent properties for attributes. |
CompilationRelaxationsAttribute attribute with the CompilationRelaxations..::.NoStringInterning enumeration member |
The attribute specifies that string literals in the assembly should not be interned. |
The attribute is ignored. |
ConstructorInfo..::.Invoke method |
Trying to call the constructor of an open generic type throws a MemberAccessException exception. |
The method call throws an ArgumentException exception. |
If the inArray parameter is a character array of zero length, the method throws a FormatException exception. |
The method returns an empty byte array (a byte array whose length is zero). |
|
If the culture name is invalid, the constructor throws an ArgumentException exception. |
The call to the constructor throws a PlatformNotSupportedException exception. |
|
iw and tl are invalid culture names. |
iw and tl are valid culture names and are equivalent to the he (Hebrew) and fil (Filipino) cultures, respectively. |
|
The bn (Bengali), bn-BD (Bengali (Bangladesh)), and bn-IN (Bengali (India)) cultures are supported. |
The constructor throws an exception because the bn, bn-BD, and bn-IN cultures are not supported. |
|
CultureInfo.InvariantCulture.DisplayName property |
The property returns "Invariant Language (Invariant Country)". |
The property returns "Invariant Language". |
Custom attribute data retrieval, such as calls to the Attribute..::.IsDefined and GetCustomAttributes methods |
The method throws an exception if the attribute type cannot be loaded. |
The method call is ignored. |
DataContractSerializer class |
XML elements must be sorted alphabetically. |
XML elements can be unordered. |
DateTime.Now.TimeOfDay.TotalMillisecond property |
The value is accurate within 100 nanoseconds. |
The value is accurate within one millisecond. |
DebuggableAttribute attribute |
The attribute instructs the runtime to provide special treatment of code within a module to provide debugging information. |
The attribute is ignored. |
Delegate..::.CreateDelegate method |
An attempt to create a delegate with incorrect arguments throws a MissingMethodException exception. |
The method returns null. |
Delegate..::.CreateDelegate method |
Trying to create a delegate to a generic method on a non-generic type throws an ArgumentException exception. |
The method throws a MissingMethodException exception. |
Enum..::.IsDefined method |
The method throws an InvalidOperationException exception if the value argument is not an integral type or a string. |
The method throws an ArgumentException exception. |
Exception filters |
A single end filter (OpCodes..::.Endfilter) instruction at the end of a filter is supported or an InvalidProgramException exception is thrown. |
Multiple end filter instructions at the end of a filter are allowed. These instructions are typically emitted by an obfuscator. |
FieldInfo..::.GetValue and FieldInfo..::.SetValue methods |
Trying to get or set the value of an instance field of an object represented by a null value throws a TargetException exception. |
The method call throws an ArgumentNullException exception. |
FieldInfo.ToString method |
For a Boolean field, the return value is "Boolean"; for an Int32 field, the return value is "Int32". |
For a Boolean field, the return value is "System.Boolean"; for an Int32 field, the return value is "System.Int32". |
FileLoadException.Data property |
The returned IDictionary object does not include an HRESULT. |
The returned IDictionary object includes an HRESULT named HResult. |
If passed a null, the method throws an ArgumentNullException exception. |
The method returns false. |
|
IsolatedStorageFile..::.GetFileNames(String) and IsolatedStorageFile..::.GetDirectoryNames(String) methods |
The searchPattern parameter consists of a literal string with wildcard characters, and the methods perform a standard file comparison. |
The methods compare files with searchPattern as they did in the previous version of Windows Phone. |
IsolatedStorageFile and IsolatedStorageFileStream classes |
Trying to perform operations on paths that do not exist or that are missing one or more subdirectories throws an IsolatedStorageException exception. |
Trying to perform operations on such paths throws a DirectoryNotFoundException exception. |
MethodInfo.Invoke method |
An ArgumentException exception is thrown if the invoked method has no default value for parameters. |
No exception is thrown. |
Mutex class |
Mutex names cannot include a backslash character. |
A backslash character is allowed in a mutex name and is replaced with another character at run time. |
NeutralResourcesLanguageAttribute attribute |
Defines the culture that provides the default resources for the application. |
The attribute is ignored. The invariant culture provides the default resources for the application. |
The location parameter determines the location of the app's default fallback resources. |
The location parameter is ignored. |
|
The starting index is updated correctly. |
The starting index is not updated correctly, and some controls rely on this behavior. |
|
The property value is a read-only ArrayList object. |
The property value is an Object array. |
|
If the object name passed to one of the overloads of the ObjectDisposedException()()() constructor is null, the property returns Empty. |
The property returns null. |
|
ParameterInfo..::.DefaultValue property |
If the parameter does not have a default value, the property returns Value. |
The property returns null. |
GetDirectoryName(String) method |
The method normalizes the path by removing redundant ".", " ", and "\" characters. |
The path is not normalized; the method only compares the string to be returned with the maximum path length. |
Referer header value set by WebClient |
The Referer header is not sent by default. You can specify a custom value for the Referer header. This behavior is consistent with the behavior of the BitmapImage class on Windows Phone 8 (8.0.10322.0) or later. |
The value of the Referer header references the installation directory of the app in the format file:///Applications/Install/<GUID>/Install/. |
Resource fallback |
The default fallback culture is the fallback culture preferred by the operating system. |
The default culture is defined by the NeutralResourcesLanguageAttribute attribute. |
The method returns the assembly's default culture, as defined by the NeutralResourcesLanguageAttribute attribute; otherwise, it returns InvariantCulture. |
The method always returns InvariantCulture. |
|
Verification fails on obfuscated phone apps. |
Verification succeeds on obfuscated phone apps. |
|
If an error occurs during an asynchronous operation, the property throws a TargetInvocationException exception, and the InnerException property of TargetInvocationException contains information about the exception. |
The exception is thrown directly and is not wrapped in a TargetInvocationException exception. |
|
BeginRead, BeginWrite, EndRead, EndWrite, and subclassed methods |
Input/output operations are performed asynchronously. |
Input/output operations are performed synchronously. |
Objects that are instantiated without explicitly specifying a buffer size have a default buffer size of 1,024 bytes. |
The default buffer size is 4,096 bytes. |
|
StreamWriter..::.Close and StreamWriter..::.Dispose methods |
If a StreamWriter object is instantiated by using a stream, closing the StreamWriter instance flushes and disposes of the underlying stream. |
The flush and dispose operations are not performed if the underlying stream is shared by multiple StreamWriter objects. |
An embedded null (U+0000) is treated like any other character. |
Windows Phone OS 7.1 quirked earlier versions, all characters that followed an embedded null were dropped. This quirk is carried forward into Windows Phone 8. |
|
The Byte Order Mark is not removed by the trim operation. |
The Byte Order Mark is treated as whitespace and removed by the trim operation. |
|
StringBuilder..::.Append(array<Char>[]()[], Int32, Int32) and StringBuilder..::.Append(String, Int32, Int32) methods |
If the count parameter is zero, the method throws an ArgumentOutOfRangeException exception. |
The method returns the value of the StringBuilder instance unchanged. |
SynchronizationContext..::.Current property |
The property returns a per-thread SynchronizationContext object. |
The property returns the same SynchronizationContext object for all threads. |
Thread..::.CurrentCulture and Thread..::.CurrentUICulture properties |
Changes to the current culture and current UI culture affect only the current thread. |
Changes to the current culture and the current UI culture affect all app threads. |
TimeSpan..::.ToString(String) and TimeSpan..::.ToString(String, IFormatProvider) methods |
The format and provider parameters produce a culture-sensitive result string. |
The format and provider parameters are ignored. |
Type..::.GetMethod, Type..::.GetMethods, PropertyInfo..::.GetGetMethod, PropertyInfo..::.GetSetMethod |
The methods do not return private inherited methods. |
The method returns private inherited methods. |
Overloads of the Type..::.GetProperty method that have a Type array parameter. |
If any element in the array is null, the method throws an ArgumentNullException exception. |
The method throws a NullReferenceException exception. |
Type..::.GetProperty and Type..::.GetProperties methods |
The method throws an AmbiguousMatchException exception if the current instance is a generic type that has a property in a base class that is hidden in the current type. |
The method retrieves the property. |
Type..::.GetProperty and Type..::.GetProperties methods with parameters of type BindingFlags. |
The methods do not return overridden properties in a base class. |
The methods can return overridden members in a base class. |
Type..::.GetType method |
The method throws an ArgumentException exception if it is passed an empty string. |
The method throws a TypeLoadException exception. |
Passing a reference type to the Type..::.MakeByRefType method. |
The method returns null. |
The method throws a TypeLoadException exception. |
Uri..::.Uri method |
Trying to instantiate a Uri object based on a relative URI that refers to a file or a resource embedded in an assembly throws a UriFormatException exception. |
Relative URIs that refer to files or resources embedded in assemblies are supported. |
If the version argument is a String, the method throws an ArgumentException exception. |
The method throws an InvalidCastException exception. |
|
If the version argument is null, the method returns 1. |
The method throws an ArgumentOutOfRangeException exception. |
|
Waits for specified objects. Calls to WaitAll may block. |
The method returns true without waiting. |
|
X509Certificate..::.X509Certificate(array<Byte>[]()[], String) and X509Certificate..::.X509Certificate(array<Byte>[]()[], String, X509KeyStorageFlags) methods |
If the byte array is null or has zero elements, the constructor throws an ArgumentException exception. |
No exception is thrown. |
X509Certificate..::.X509Certificate and X509Certificate..::.Import methods that have an X509KeyStorageFlags parameter |
If the flags are invalid, the object creation constructor or method throws an ArgumentException exception. |
The constructor or method throws a NotSupportedException exception. |
XmlElementAttribute..::.ElementName property |
If the name is not unique, the XML serializer throws an InvalidOperationException exception. |
Duplicate element names are permitted. |
XmlSerializer class |
Serialized types must have a default (parameterless) constructor. |
It is not necessary for serialized types to have a default constructor. |
XmlSerializer class |
By default, XML serialization assumes that XML is UTF-8 encoded and emits an encoding=utf-8 attribute. |
The serializer does not emit the encoding attribute. |
XmlSerializer class |
The serializer throws an exception if a derived type defines a member with the same name as its base type. |
The serializer allows a derived type to define a member with the same name as its base type. |
XmlSerializer class |
Types with properties of type Nullable<(Of <(T>)>) are not serializable. |
The types with properties of type are serializable. |
XmlSerializer class |
Trying to deserialize an empty XML file throws an exception. |
No exception is thrown. |
XmlSerializer class |
The serializer expects element data to be tagged with the XmlRootAttribute attribute. |
If there is no XmlRootAttribute attribute, XmlArrayItemAttribute can be applied to element data. |
XmlSerializer..::.Deserialize and other XML read operations |
The read operation returns any trailing nulls at the end of a byte stream, |
The read operation discards any trailing nulls at the end of a byte stream. |