SDK style 是一种新的项目文件格式。与传统的 .NET Framework 项目文件相比,新的 SDK style 提供了更简洁、可读性更好的语法,同时还引入了更多的灵活性和功能。
新风格的 csproj 文件是从 VS2017 版本开始引入和支持的。在 VS2015 和更早的版本,使用的是传统 csproj 文件格式。
新老工程文件
先看看老的工程文件是个什么样子。新建一个 .NET Framework 窗体项目:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 
 | <?xml version="1.0" encoding="utf-8"?><Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
 <PropertyGroup>
 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
 <ProjectGuid>{013DB7AC-1A98-4BB9-8D01-C6CEA6C8AB78}</ProjectGuid>
 <OutputType>WinExe</OutputType>
 <RootNamespace>WindowsFormsApp1</RootNamespace>
 <AssemblyName>WindowsFormsApp1</AssemblyName>
 <TargetFrameworkVersion>v4.8.1</TargetFrameworkVersion>
 <FileAlignment>512</FileAlignment>
 <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
 <Deterministic>true</Deterministic>
 </PropertyGroup>
 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
 <PlatformTarget>AnyCPU</PlatformTarget>
 <DebugSymbols>true</DebugSymbols>
 <DebugType>full</DebugType>
 <Optimize>false</Optimize>
 <OutputPath>bin\Debug\</OutputPath>
 <DefineConstants>DEBUG;TRACE</DefineConstants>
 <ErrorReport>prompt</ErrorReport>
 <WarningLevel>4</WarningLevel>
 </PropertyGroup>
 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
 <PlatformTarget>AnyCPU</PlatformTarget>
 <DebugType>pdbonly</DebugType>
 <Optimize>true</Optimize>
 <OutputPath>bin\Release\</OutputPath>
 <DefineConstants>TRACE</DefineConstants>
 <ErrorReport>prompt</ErrorReport>
 <WarningLevel>4</WarningLevel>
 </PropertyGroup>
 <ItemGroup>
 <Reference Include="System" />
 <Reference Include="System.Core" />
 <Reference Include="System.Xml.Linq" />
 <Reference Include="System.Data.DataSetExtensions" />
 <Reference Include="Microsoft.CSharp" />
 <Reference Include="System.Data" />
 <Reference Include="System.Deployment" />
 <Reference Include="System.Drawing" />
 <Reference Include="System.Net.Http" />
 <Reference Include="System.Windows.Forms" />
 <Reference Include="System.Xml" />
 </ItemGroup>
 <ItemGroup>
 <Compile Include="Form1.cs">
 <SubType>Form</SubType>
 </Compile>
 <Compile Include="Form1.Designer.cs">
 <DependentUpon>Form1.cs</DependentUpon>
 </Compile>
 <Compile Include="Program.cs" />
 <Compile Include="Properties\AssemblyInfo.cs" />
 <EmbeddedResource Include="Properties\Resources.resx">
 <Generator>ResXFileCodeGenerator</Generator>
 <LastGenOutput>Resources.Designer.cs</LastGenOutput>
 <SubType>Designer</SubType>
 </EmbeddedResource>
 <Compile Include="Properties\Resources.Designer.cs">
 <AutoGen>True</AutoGen>
 <DependentUpon>Resources.resx</DependentUpon>
 </Compile>
 <None Include="Properties\Settings.settings">
 <Generator>SettingsSingleFileGenerator</Generator>
 <LastGenOutput>Settings.Designer.cs</LastGenOutput>
 </None>
 <Compile Include="Properties\Settings.Designer.cs">
 <AutoGen>True</AutoGen>
 <DependentUpon>Settings.settings</DependentUpon>
 <DesignTimeSharedInput>True</DesignTimeSharedInput>
 </Compile>
 </ItemGroup>
 <ItemGroup>
 <None Include="App.config" />
 </ItemGroup>
 <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
 </Project>
 
 | 
再看看新的工程文件:
| 12
 3
 4
 5
 6
 
 | <Project Sdk="Microsoft.NET.Sdk"><PropertyGroup>
 <OutputType>WinExe</OutputType>
 <TargetFramework>net7.0-windows</TargetFramework>
 </PropertyGroup>
 </Project>
 
 | 
高下立判,新风格的工程文件精简多了!
常用设置
OutputType
用于指定项目输出的文件类型。支持以下值:
| 值 | 说明 | 
| Library | DLL 动态库 | 
| Exe | 控制台程序 | 
| WinExe | 窗口程序 | 
TargetFramework
TargetFramework 用于指定项目的目标框架。它表示项目所针对的特定台或运行时环境。
| 12
 3
 
 | <PropertyGroup><TargetFramework>net48</TargetFramework>
 </PropertyGroup>
 
 | 
支持的值看这里:支持的目标框架。
但是一般来说我们不应该指定这个值,而应该用复数版本的参数TargetFrameworks。
TargetFrameworks
TargetFrameworks 允许针对多个不同的目标框架进行构建,每个目标框架通过分号进行分隔:
| 12
 3
 
 | <PropertyGroup><TargetFrameworks>netcoreapp3.1;net462</TargetFrameworks>
 </PropertyGroup>
 
 | 
这是必填的参数,指示工程使用哪些框架编译。
AppendTargetFrameworkToOutputPath
AppendTargetFrameworkToOutputPath 属性决定了输出路径中是否追加TargetFramework的值,默认为true。
PlatformTarget 用于指定项目的目标平台。它决定了编译后的文件的实际架构。
可能的值:AnyCPU、x86、x64、arm、arm64。
来自 Microsoft.NET.RuntimeIdentifierInference.targets 文件中的片段:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 
 | <Choose>
 <When Condition="'$(PlatformTarget)' != '' or '$(RuntimeIdentifier)' == ''" />
 
 <When Condition="$(RuntimeIdentifier.EndsWith('-x86')) or $(RuntimeIdentifier.Contains('-x86-'))">
 <PropertyGroup>
 <PlatformTarget>x86</PlatformTarget>
 </PropertyGroup>
 </When>
 
 <When Condition="$(RuntimeIdentifier.EndsWith('-x64')) or $(RuntimeIdentifier.Contains('-x64-'))">
 <PropertyGroup>
 <PlatformTarget>x64</PlatformTarget>
 </PropertyGroup>
 </When>
 
 <When Condition="$(RuntimeIdentifier.EndsWith('-arm')) or $(RuntimeIdentifier.Contains('-arm-'))">
 <PropertyGroup>
 <PlatformTarget>arm</PlatformTarget>
 </PropertyGroup>
 </When>
 
 <When Condition="$(RuntimeIdentifier.EndsWith('-arm64')) or $(RuntimeIdentifier.Contains('-arm64-'))">
 <PropertyGroup>
 <PlatformTarget>arm64</PlatformTarget>
 </PropertyGroup>
 </When>
 
 <Otherwise>
 <PropertyGroup>
 <PlatformTarget>AnyCPU</PlatformTarget>
 </PropertyGroup>
 </Otherwise>
 </Choose>
 
 | 
所以PlatformTarget不需要手动设置。
ImplicitUsings
ImplicitUsings 用于指定在项目代码中隐式引用的命名空间(using)。可以在项目中省略对特定命名空间的显式引用,从而简化代码。
| 12
 3
 
 | <PropertyGroup><ImplicitUsings>enable</ImplicitUsings>
 </PropertyGroup>
 
 | 
当 UseWindowsForms 属性设置为 true 时,项目将引用并使用 Windows Forms 库,以便开发 Windows Forms 应用程序。
| 12
 3
 
 | <PropertyGroup><UseWindowsForms>true</UseWindowsForms>
 </PropertyGroup>
 
 | 
UseWPF
当 UseWPF 属性设置为 true 时,项目将引用并使用 WPF 库,以便开发 WPF 程序。
| 12
 3
 
 | <PropertyGroup><UseWPF>true</UseWPF>
 </PropertyGroup>
 
 | 
RuntimeIdentifier
RID 是运行时标识符的缩写。 RID 值用于标识应用程序运行所在的目标平台。.NET 包使用它们来表示 NuGet 包中特定于平台的资产。
在编译时它会根据PlatformTarget属性自动设置,不需要手动设置。
AppendRuntimeIdentifierToOutputPath
AppendRuntimeIdentifierToOutputPath 属性决定了输出路径中是否追加RuntimeIdentifier的值,默认为true。
Nullable
是否启用 可空类型 特性。
| 1
 | <Nullable>enable</Nullable>
 | 
打开 Nullable 设置可以提高代码的可读性、减少潜在的空引用异常,并帮助你编写更健壮和高质量的代码。
LangVersion
LangVersion 用于设置使用 C# 语言的版本。不设置时会有 默认值。
原则上版本越高越好,毕竟使用新特性会使开发效率提高。
参考
常用的 MSBuild 项目属性
.NET 项目 SDK
.NET RID 目录
Platform vs. PlatformTarget In Any .NET Build