This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
Access to this page requires authorization. You can trysigning in orchanging directories.
Access to this page requires authorization. You can trychanging directories.
When you target a framework in an app or library, you're specifying the set of APIs that you'd like to make available to the app or library. You specify the target framework in your project file using a target framework moniker (TFM).
An app or library can target a version of.NET Standard. .NET Standard versions represent standardized sets of APIs across all .NET implementations. For example, a library can target .NET Standard 1.6 and gain access to APIs that function across .NET Core and .NET Framework using the same codebase.
An app or library can also target a specific .NET implementation to gain access to implementation-specific APIs. For example, an app that targets Universal Windows Platform (UWP,uap10.0) has access to APIs that compile for devices that run Windows 10.
For some target frameworks, such as .NET Framework, the APIs are defined by the assemblies that the framework installs on a system and may include application framework APIs (for example, ASP.NET).
For package-based target frameworks (for example, .NET 5+, .NET Core, and .NET Standard), the APIs are defined by the NuGet packages included in the app or library.
The following table defines the most common target frameworks, how they're referenced, and which version of.NET Standard they implement. These target framework versions are the latest stable versions. Prerelease versions aren't shown. Atarget framework moniker (TFM) is a standardized token format for specifying the target framework of a .NET app or library.
| Target framework | Latest stable version | Target framework moniker (TFM) | Implemented .NET Standard version |
|---|---|---|---|
| .NET 10 | 10 | net10.0 | 2.1 |
| .NET 9 | 9 | net9.0 | 2.1 |
| .NET 8 | 8 | net8.0 | 2.1 |
| .NET Standard | 2.1 | netstandard2.1 | N/A |
| .NET Core | 3.1 | netcoreapp3.1 | 2.1 |
| .NET Framework | 4.8.1 | net481 | 2.0 |
A target framework is typically referenced by a TFM. The following table shows the target frameworks supported by the .NET SDK and the NuGet client. Equivalents are shown within brackets. For example,win81 is an equivalent TFM tonetcore451.
| Target Framework | TFM |
|---|---|
| .NET 5+ (and .NET Core) | netcoreapp1.0 netcoreapp1.1 netcoreapp2.0 netcoreapp2.1 netcoreapp2.2 netcoreapp3.0 netcoreapp3.1 net5.0* net6.0* net7.0* net8.0* net9.0* net10.0* |
| .NET Standard | netstandard1.0 netstandard1.1 netstandard1.2 netstandard1.3 netstandard1.4 netstandard1.5 netstandard1.6 netstandard2.0 netstandard2.1 |
| .NET Framework | net11 net20 net35 net40 net403 net45 net451 net452 net46 net461 net462 net47 net471 net472 net48 net481 |
| Windows Store | netcore [netcore45] netcore45 [win] [win8] netcore451 [win81] |
| .NET nanoFramework | netnano1.0 |
| .NET Micro Framework | netmf |
| Silverlight | sl4 sl5 |
| Windows Phone | wp [wp7] wp7 wp75 wp8 wp81 wpa81 |
| Universal Windows Platform | uap [uap10.0] uap10.0 [win10] [netcore50] |
* .NET 5 and later TFMs include some operating system-specific variations. For more information, see the following section,OS-specific TFMs.
Thenet8.0,net9.0, andnet10.0 TFMs include technologies that work across different platforms. Specifying anOS-specific TFM makes APIs that are specific to an operating system available to your app, for example, Windows Forms or iOS bindings. OS-specific TFMs also inherit every API available to their base TFM, for example, thenet10.0 TFM.
The following table shows the compatibility of the .NET 8+ TFMs.
| TFM | Compatible with |
|---|---|
net8.0 | (Subsequent version ofnet7.0) |
net8.0-android | (Subsequent version ofnet7.0-android) |
net8.0-browser | Everything inherited fromnet8.0 |
net8.0-ios | (Subsequent version ofnet7.0-ios) |
net8.0-maccatalyst | (Subsequent version ofnet7.0-maccatalyst) |
net8.0-macos | (Subsequent version ofnet7.0-macos) |
net8.0-tizen | (Subsequent version ofnet7.0-tizen) |
net8.0-tvos | (Subsequent version ofnet7.0-tvos) |
net8.0-windows | (Subsequent version ofnet7.0-windows) |
net9.0 | (Subsequent version ofnet8.0) |
net9.0-android | (Subsequent version ofnet8.0-android) |
net9.0-browser | (Subsequent version ofnet8.0-browser) |
net9.0-ios | (Subsequent version ofnet8.0-ios) |
net9.0-maccatalyst | (Subsequent version ofnet8.0-maccatalyst) |
net9.0-macos | (Subsequent version ofnet8.0-macos) |
net9.0-tizen | (Subsequent version ofnet8.0-tizen) |
net9.0-tvos | (Subsequent version ofnet8.0-tvos) |
net9.0-windows | (Subsequent version ofnet8.0-windows) |
net10.0 | (Subsequent version ofnet9.0) |
net10.0-android | (Subsequent version ofnet9.0-android) |
net10.0-browser | (Subsequent version ofnet9.0-browser) |
net10.0-ios | (Subsequent version ofnet9.0-ios) |
net10.0-maccatalyst | (Subsequent version ofnet9.0-maccatalyst) |
net10.0-macos | (Subsequent version ofnet9.0-macos) |
net10.0-tizen | (Subsequent version ofnet9.0-tizen) |
net10.0-tvos | (Subsequent version ofnet9.0-tvos) |
net10.0-windows | (Subsequent version ofnet9.0-windows) |
To make your app portable across different platforms but still have access to OS-specific APIs, you can target multiple OS-specific TFMs and add platform guards around OS-specific API calls using#if preprocessor directives. For a list of the available symbols, seePreprocessor symbols.
Use these guidelines to determine which TFM to use in your app:
net10.0. This includes most libraries but also ASP.NET Core and Entity Framework.net10.0-windows.net10.0, but might also target additional platform-specific flavors to light-up more APIs or features.You can also specify an optional OS version at the end of an OS-specific TFM, for example,net8.0-ios17.2. The version indicates which APIs are available to your app or library. It doesn't control the OS version that your app or library supports at run time. It's used to select the reference assemblies that your project compiles against, and to select assets from NuGet packages. Think of this version as the "platform version" or "OS API version" to disambiguate it from the run-time OS version.
The .NET SDK is designed to be able to support newly released APIs for an individual platform without a new version of the base TFM. This enables you to access platform-specific functionality without waiting for a major release of .NET. You can gain access to these newly released APIs by incrementing the platform version in the TFM. For example, if the Android platform added API level 34 APIs in a .NET 8.0.x SDK update, you could access them by using the TFMnet8.0-android34.0.
When an OS-specific TFM doesn't specify the platform version explicitly, it has an implied value that can be inferred from the base TFM and platform name. For example, the default platform version for Android in .NET 9 is35.0, which means thatnet9.0-android is shorthand for the canonicalnet9.0-android35.0 TFM. The shorthand form is intended for use in project files only, and is expanded to the canonical form by the .NET SDK's MSBuild targets before being passed to other tools, such as NuGet.
The following table shows thedefault target platform version (TPV) for Android and iOS for each .NET release.If you want to use the latest bindings, use the default (that is, don't specify an OS version).
| .NET version | Android | iOS |
|---|---|---|
| .NET 8 | 34.0 | 17.2 |
| .NET 9 | 35.0 | 18.0 |
| .NET 10 | 36.0 | 18.7 |
Starting in .NET 9, when service releases introduce support for a later TPV (which will always have the samemajor version number as when the .NET version was initially released), the earliest supported TPV for that .NET version will remain supported. For example, for .NET 9, the earliest supported iOS version, 18.0, will remain supported, even when a service release adds support for the latest iOS 18.x version.If you need to use the earliest bindings for a .NET release, use a specific OS version number in your TFM.
Note
On Apple platforms (iOS, macOS, tvOS, and Mac Catalyst) in .NET 8 and earlier,the default TPV is the latest supported version in the currently installed workload.That means that updating the iOS workload in .NET 8, for example, might result in a higher defaultTPV, if support for a new version of iOS has been added in that workload. In the preceding table,the default TPV is the version in the initial release for the stated .NET version.
Starting in .NET 9, this special behavior only applies toexecutable projects. The default TPV for library projects now stays the same for the entirety of a major .NET release, like all other platforms.
If your app references a package that has multiple assets for different TFMs, the assets that are closer in version number are preferred. For example, if your app targetsnet9.0-ios and the package offers assets fornet9.0 andnet8.0-ios, thenet9.0 assets are used. For more information, seePrecedences.
Although a platform-specific app or library is compiled against APIs from a specific version of that OS, you can make it compatible with earlier OS versions by adding theSupportedOSPlatformVersion property to your project file. TheSupportedOSPlatformVersion property indicates the minimum OS version required to run your app or library. If you don't explicitly specify this minimum run-time OS version in the project, it defaults to the platform version from the TFM.
For your app to run correctly on an older OS version, it can't call APIs that don't exist on that version of the OS. However, you can add guards around calls to newer APIs so they are only called when running on a version of the OS that supports them. This pattern allows you to design your app or library to support running on older OS versions while taking advantage of newer OS functionality when running on newer OS versions.
TheSupportedOSPlatformVersion value (whether explicit or default) is used by theplatform compatibility analyzer, which detects and warns about unguarded calls to newer APIs. It's burned into the project's compiled assembly as anUnsupportedOSPlatformAttribute assembly attribute, so that the platform compatibility analyzer can detect unguarded calls to that assembly's APIs from projects with a lowerSupportedOSPlatformVersion value. On some platforms, theSupportedOSPlatformVersion value affects platform-specific app packaging and build processes, which is covered in the documentation for those platforms.
The following example is an excerpt of a project file that uses theTargetFramework andSupportedOSPlatformVersion MSBuild properties to specify that the app or library has access to iOS 15.0 APIs but supports running on iOS 13.0 and higher:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net6.0-ios15.0</TargetFramework> <SupportedOSPlatformVersion>13.0</SupportedOSPlatformVersion> </PropertyGroup> ...</Project>Target frameworks are specified in a project file. When a single target framework is specified, use theTargetFramework element. The following console app project file demonstrates how to target .NET 10:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net10.0</TargetFramework> </PropertyGroup></Project>When you specify multiple target frameworks, you can conditionally reference assemblies for each target framework. In your code, you can conditionally compile against those assemblies by usingpreprocessor symbols withif-then-else logic.
The following library project targets APIs of .NET Standard (netstandard1.4) and .NET Framework (net40 andnet45). Use the pluralTargetFrameworks element with multiple target frameworks. TheCondition attributes include implementation-specific packages when the library is compiled for the two .NET Framework TFMs:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>netstandard1.4;net40;net45</TargetFrameworks> </PropertyGroup> <!-- Conditionally obtain references for the .NET Framework 4.0 target --> <ItemGroup Condition=" '$(TargetFramework)' == 'net40' "> <Reference Include="System.Net" /> </ItemGroup> <!-- Conditionally obtain references for the .NET Framework 4.5 target --> <ItemGroup Condition=" '$(TargetFramework)' == 'net45' "> <Reference Include="System.Net.Http" /> <Reference Include="System.Threading.Tasks" /> </ItemGroup></Project>Within your library or app, you write conditional code usingpreprocessor directives to compile for each target framework:
public class MyClass{ static void Main() {#if NET40 Console.WriteLine("Target framework: .NET Framework 4.0");#elif NET45 Console.WriteLine("Target framework: .NET Framework 4.5");#else Console.WriteLine("Target framework: .NET Standard 1.4");#endif }}The build system is aware of preprocessor symbols representing the target frameworks shown in theSupported target framework versions table when you're using SDK-style projects. To convert a .NET Standard, .NET Core, or .NET 5+ TFM to a preprocessor symbol, replace dots and hyphens with an underscore, and change lowercase letters to uppercase (for example, the symbol fornetstandard2.0 isNETSTANDARD2_0).
You can disable generation of these symbols via theDisableImplicitFrameworkDefines property. For more information about this property, seeDisableImplicitFrameworkDefines.
The complete list of preprocessor symbols for .NET target frameworks is:
| Target Frameworks | Symbols | Additional symbols (available in .NET 5+ SDKs) | Platform symbols (available only when you specify an OS-specific TFM) |
|---|---|---|---|
| .NET Framework | NETFRAMEWORK,NET481,NET48,NET472,NET471,NET47,NET462,NET461,NET46,NET452,NET451,NET45,NET40,NET35,NET20 | NET48_OR_GREATER,NET472_OR_GREATER,NET471_OR_GREATER,NET47_OR_GREATER,NET462_OR_GREATER,NET461_OR_GREATER,NET46_OR_GREATER,NET452_OR_GREATER,NET451_OR_GREATER,NET45_OR_GREATER,NET40_OR_GREATER,NET35_OR_GREATER,NET20_OR_GREATER | |
| .NET Standard | NETSTANDARD,NETSTANDARD2_1,NETSTANDARD2_0,NETSTANDARD1_6,NETSTANDARD1_5,NETSTANDARD1_4,NETSTANDARD1_3,NETSTANDARD1_2,NETSTANDARD1_1,NETSTANDARD1_0 | NETSTANDARD2_1_OR_GREATER,NETSTANDARD2_0_OR_GREATER,NETSTANDARD1_6_OR_GREATER,NETSTANDARD1_5_OR_GREATER,NETSTANDARD1_4_OR_GREATER,NETSTANDARD1_3_OR_GREATER,NETSTANDARD1_2_OR_GREATER,NETSTANDARD1_1_OR_GREATER,NETSTANDARD1_0_OR_GREATER | |
| .NET 5+ (and .NET Core) | NET,NET10_0,NET9_0,NET8_0,NET7_0,NET6_0,NET5_0,NETCOREAPP,NETCOREAPP3_1,NETCOREAPP3_0,NETCOREAPP2_2,NETCOREAPP2_1,NETCOREAPP2_0,NETCOREAPP1_1,NETCOREAPP1_0 | NET10_0_OR_GREATER,NET9_0_OR_GREATER,NET8_0_OR_GREATER,NET7_0_OR_GREATER,NET6_0_OR_GREATER,NET5_0_OR_GREATER,NETCOREAPP3_1_OR_GREATER,NETCOREAPP3_0_OR_GREATER,NETCOREAPP2_2_OR_GREATER,NETCOREAPP2_1_OR_GREATER,NETCOREAPP2_0_OR_GREATER,NETCOREAPP1_1_OR_GREATER,NETCOREAPP1_0_OR_GREATER | ANDROID,BROWSER,IOS,MACCATALYST,MACOS,TVOS,WINDOWS,[OS][version] (for exampleIOS15_1),[OS][version]_OR_GREATER (for exampleIOS15_1_OR_GREATER) |
Note
<framework>_OR_GREATER symbols are defined for the version you're targeting and all earlier versions. For example, if you're targeting .NET Framework 2.0, the following symbols are defined:NET20,NET20_OR_GREATER,NET11_OR_GREATER, andNET10_OR_GREATER.NETSTANDARD<x>_<y>_OR_GREATER symbols are only defined for .NET Standard targets, and not for targets that implement .NET Standard, such as .NET Core and .NET Framework.TargetFramework property andNuGet.The following target frameworks are deprecated. Packages that target these target frameworks should migrate to the indicated replacements.
| Deprecated TFM | Replacement |
|---|---|
| aspnet50 aspnetcore50 dnxcore50 dnx dnx45 dnx451 dnx452 | netcoreapp |
| dotnet dotnet50 dotnet51 dotnet52 dotnet53 dotnet54 dotnet55 dotnet56 | netstandard |
| netcore50 | uap10.0 |
| win | netcore45 |
| win8 | netcore45 |
| win81 | netcore451 |
| win10 | uap10.0 |
| winrt | netcore45 |
Was this page helpful?
Need help with this topic?
Want to try using Ask Learn to clarify or guide you through this topic?
Was this page helpful?
Want to try using Ask Learn to clarify or guide you through this topic?