从 .NET Framework 迁移到 .NET Core 的中断性变更

若要将应用从 .NET Framework 迁移到 .NET Core 1.0 至 3.1,本文中列出的中断性变更可能会影响你。 中断性变更按类别进行分组,并且在这些类别中按引入的 .NET Core 版本进行分组。

备注

本文不是 .NET Framework 与 .NET Core 之间的中断性变更的完整列表。 在我们发现最重要的中断性变更时,会将其添加到此处。

Core .NET 库

.NET Core 2.1

UseShellExecute 默认值更改

ProcessStartInfo.UseShellExecute 在 .NET Core 上的默认值为 false。 在 .NET Framework 上,其默认值为 true

更改描述

可以通过 Process.Start 直接启动应用程序,例如,使用 Process.Start("mspaint.exe") 代码启动画图。 如果 ProcessStartInfo.UseShellExecute 设置为 true,它还允许间接启动关联的应用程序。 在 .NET Framework 上,ProcessStartInfo.UseShellExecute 的默认值 true,这意味着,如果已将 .txt 文件与该编辑器相关联,则 Process.Start("mytextfile.txt") 会启动记事本。 若要防止在 .NET Framework 上间接启动应用,必须将 ProcessStartInfo.UseShellExecute 显式设置为 false。 在 .NET Core 中,ProcessStartInfo.UseShellExecute 的默认值为 false。 这意味着,默认情况下,在调用 Process.Start 时不会启动关联的应用程序。

只有当 ProcessStartInfo.UseShellExecutetrue 时,System.Diagnostics.ProcessStartInfo 上的以下属性才起作用:

出于性能方面的考虑,.NET Core 中引入了此更改。 通常情况下,Process.Start 用于直接启动应用程序。 直接启动应用并不需要使用 Windows shell,也不会产生关联的性能成本。 为了更快地使此情况默认化,.NET Core 将 ProcessStartInfo.UseShellExecute 的默认值更改为 false。 如果需要,可以选择慢速路径。

引入的版本

2.1

备注

在早期版本的 .NET Core 中,没有为 Windows 实现 UseShellExecute

如果应用依赖于旧行为,请调用 Process.Start(ProcessStartInfo),并将 UseShellExecute 设置为 ProcessStartInfo 对象上的 true

类别

Core .NET 库

受影响的 API


.NET Core 1.0

FileSystemInfo.Attributes 引发的 UnauthorizedAccessException

在 .NET Core 中,当调用方尝试设置文件属性值但没有写权限时,将引发 UnauthorizedAccessException

更改描述

在 .NET Framework 中,当调用方尝试在 FileSystemInfo.Attributes 中设置文件属性值但没有写权限时,将引发 ArgumentException。 在 .NET Core 中,将改为引发 UnauthorizedAccessException。 (在 .NET Core 中,如果调用方尝试设置无效的文件属性,则仍会引发 ArgumentException。)

引入的版本

1.0

根据需要修改任何 catch 语句不是捕获 ArgumentException,而是捕获或者除它之外还捕获 UnauthorizedAccessException

类别

Core .NET 库

受影响的 API


不支持处理损坏状态异常

不支持在 .NET Core 中处理损坏进程状态异常。

更改描述

以前,损坏进程状态异常可以由托管代码异常处理程序进行捕获和处理,例如在 C# 中使用 try-catch 语句。

从 .NET Core 1.0 开始,损坏进程状态异常无法由托管代码进行处理。 公共语言运行时不会将损坏进程状态异常传递给托管代码。

引入的版本

1.0

通过解决导致这些异常的情况来避免需要处理损坏进程状态异常。 如果绝对有必要处理损坏进程状态异常,请在 C 或 C++ 代码中编写异常处理程序。

类别

Core .NET 库

受影响的 API


UriBuilder 属性不再预置前导字符

如果已存在一个字符,则 UriBuilder.Fragment 不再预置前导 # 字符,且 UriBuilder.Query 不再预置前导 ? 字符。

更改描述

在 .NET Framework 中,UriBuilder.FragmentUriBuilder.Query 属性始终将 #? 字符分别预置到所存储的值。 如果字符串已经包含其中一个前导字符,则此行为可能会导致存储值中包含多个 #? 字符。 例如,UriBuilder.Fragment 的值可能会变为 ##main

从 .NET Core 1.0 开始,如果在字符串的开头已经存在一个字符,则这些属性将不再将 #? 字符预置到存储值之前。

引入的版本

1.0

设置属性值时,不再需要显式删除这些前导字符。 这在追加值时特别有用,因为不再需要在每次追加时删除前导 #?

例如,下面的代码片段显示 .NET Framework 和 .NET Core 之间的行为差异。

var builder = new UriBuilder();
builder.Query = "one=1";
builder.Query += "&two=2";
builder.Query += "&three=3";
builder.Query += "&four=4";

Console.WriteLine(builder.Query);
  • 在 .NET Framework 中,输出为 ????one=1&two=2&three=3&four=4
  • 在 .NET Core 中,输出为 ?one=1&two=2&three=3&four=4

类别

Core .NET 库

受影响的 API


Process.StartInfo 对未启动的进程引发 InvalidOperationException

对于你的代码未启动的进程,读取其 Process.StartInfo 属性会引发 InvalidOperationException

更改描述

在 .NET Framework 中,访问你的代码未启动的进程的 Process.StartInfo 属性将返回虚拟 ProcessStartInfo 对象。 虚拟对象包含其所有属性(EnvironmentVariables 除外)的默认值。

从 .NET Core 1.0 开始,如果读取你未启动的进程的 Process.StartInfo 属性(即通过调用 Process.Start),则会引发 InvalidOperationException

引入的版本

1.0

不要访问你的代码未启动的进程的 Process.StartInfo 属性。 例如,不要读取 Process.GetProcesses 返回的进程的此属性。

类别

Core .NET 库

受影响的 API


密码

.NET Core 2.1

已考虑 SignedCms.ComputeSignature 的布尔参数

在 .NET Core 中,已考虑 SignedCms.ComputeSignature(CmsSigner, Boolean) 方法的布尔 silent 参数。 如果将此参数设置为 true,则不会显示 PIN 提示。

更改描述

在 .NET Framework 中,SignedCms.ComputeSignature(CmsSigner, Boolean) 方法的 silent 参数将被忽略,并且如果提供程序要求,则始终会显示 PIN 提示。 在 .NET Core 中,已考虑 silent 参数,并且如果将其设置为 true,则即使提供程序要求也不会显示 PIN 提示。

在 2.1 版的 .NET Core 中引入了对 CMS/PKCS #7 消息的支持。

引入的版本

2.1

为了确保在需要时显示 PIN 提示,桌面应用程序应调用 SignedCms.ComputeSignature(CmsSigner, Boolean) 并将 Boolean 参数设置为 false。 无论是否禁用了静默上下文,所产生的行为都与 .NET Framework 上的行为相同。

类别

密码

受影响的 API


MSBuild

.NET Core 3.0

资源清单文件名更改

从 .NET Core 3.0 开始,默认情况下,MSBuild 会为资源文件生成不同的清单文件名。

引入的版本

3.0

更改描述

在 .NET Core 3.0 之前,如果没有为项目文件中的 EmbeddedResource 项指定 LogicalNameManifestResourceNameDependentUpon 元数据,则 MSBuild 会在 <RootNamespace>.<ResourceFilePathFromProjectRoot>.resources 模式中生成清单文件名。 如果未在项目文件中定义 RootNamespace,则其默认为项目名称。 例如,根项目目录中名为“Form1.resx”的资源文件的生成清单名称是“MyProject.Form1.resources”。

从 .NET Core 3.0 开始,如果资源文件与同名的源文件(例如 Form1.resx 和 Form1.cs)并置,则 MSBuild 将使用源文件中的类型信息在 <Namespace>.<ClassName>.resources 模式中生成清单文件名。 命名空间和类名称是从并置源文件的第一个类型中提取的。 例如,与名为“Form1.cs”的源文件并置的、名为“Form1.resx”的资源文件的生成清单名称是“MyNamespace.Form1.resources”。 需要注意的一点是,文件名的第一部分不同于早期版本的 .NET Core(是 MyNamespace,而不是 MyProject)。

备注

如果已在项目文件中的 EmbeddedResource 项上指定 LogicalNameManifestResourceNameDependentUpon 元数据,则此更改不会影响该资源文件。

此重大更改是在 .NET Core 项目中添加 EmbeddedResourceUseDependentUponConvention 属性时引入的。 默认情况下,不会在 .NET Core 项目文件中显式列出资源文件,因此它们没有 DependentUpon 元数据来指定如何命名生成的 .resources 文件。 如果 EmbeddedResourceUseDependentUponConvention 设置为 true(默认值),则 MSBuild 将查找并置的源文件,并从该文件中提取命名空间和类名。 如果将 EmbeddedResourceUseDependentUponConvention 设置为 false,则 MSBuild 将根据之前的行为生成清单名称,将 RootNamespace 和相对文件路径组合在一起。

在大多数情况下,开发人员不需要执行任何操作,应用应可以继续工作。 但是,如果此更改造成应用中断运行,你可以:

  • 将代码更改为需要新的清单名称。

  • 在项目文件中将 EmbeddedResourceUseDependentUponConvention 设置为 false,以选择退出新命名约定。

    <PropertyGroup>
      <EmbeddedResourceUseDependentUponConvention>false</EmbeddedResourceUseDependentUponConvention>
    </PropertyGroup>
    

类别

MSBuild

受影响的 API

不可用


网络

.NET Core 2.0

WebClient.CancelAsync 并不总是立即取消

自 .NET Core 2.0 起,如果响应已开始提取,则调用 WebClient.CancelAsync() 不会立即取消请求。

更改描述

以前,调用 WebClient.CancelAsync() 会立即取消请求。 自 .NET Core 2.0 起,只有当响应尚未开始提取时,调用 WebClient.CancelAsync() 才会立即取消请求。 如果响应已开始提取,则只有在读取完整响应之后才会取消请求。

此更改已实现,因为 WebClient API 已弃用,取而代之的是 HttpClient

引入的版本

2.0

使用 System.Net.Http.HttpClient 类,而不是已弃用的 System.Net.WebClient

类别

网络

受影响的 API


Windows 窗体

已在 .NET Core 的版本 3.0 中添加 Windows 窗体支持。 如果将 Windows 窗体应用从 .NET Framework 迁移到 .NET Core,此处列出的中断性变更可能会影响你的应用。

.NET Core 3.1

已删除的控件

从 .NET Core 3.1 开始,某些 Windows 窗体控件不再可用。

更改描述

从 .NET Core 3.1 开始,各种 Windows 窗体控件不再可用。 .NET Framework 2.0 中引入改进了设计和支持的替换控件。 弃用的控件之前已从设计器工具箱中删除,但仍可供使用。

以下类型不再可用:

引入的版本

3.1

每个已删除的控件都有一个推荐的替换控件。 请参阅以下表:

已删除的控件 (API) 推荐的替换控件 已删除的关联 API
ContextMenu ContextMenuStrip
DataGrid DataGridView DataGridCell、DataGridRow、DataGridTableCollection、DataGridColumnCollection、DataGridTableStyle、DataGridColumnStyle、DataGridLineStyle、DataGridParentRowsLabel、DataGridParentRowsLabelStyle、DataGridBoolColumn、DataGridTextBox、GridColumnStylesCollection、GridTableStylesCollection、HitTestType
MainMenu MenuStrip
菜单 ToolStripDropDown、ToolStripDropDownMenu MenuItemCollection
MenuItem ToolStripMenuItem
ToolBar ToolStrip ToolBarAppearance
ToolBarButton ToolStripButton ToolBarButtonClickEventArgs、ToolBarButtonClickEventHandler、ToolBarButtonStyle、ToolBarTextAlign

类别

Windows 窗体

受影响的 API


如果显示工具提示,则不引发 CellFormatting 事件

现在,当鼠标悬停和通过键盘选择时,DataGridView 将显示单元格的文本和错误工具提示。 如果显示工具提示,则不会引发 DataGridView.CellFormatting 事件。

更改描述

在 .NET Core 3.1 之前,将 ShowCellToolTips 属性设置为 trueDataGridView 会在鼠标悬停在单元格上方时显示单元格文本和错误的工具提示。 之前,通过键盘选择单元格时(例如通过使用 Tab 键、快捷键或箭头导航),不显示工具提示。 如果用户编辑了单元格,然后在 DataGridView 仍处于编辑模式时将鼠标悬停在未设置 ToolTipText 属性的单元格上,则会引发 CellFormatting 事件,对要在单元格中显示的单元格文本进行格式化。

为满足辅助功能标准,自 .NET Core 3.1 起,将 ShowCellToolTips 属性设置为 trueDataGridView 不仅在鼠标悬停在单元格上时会显示单元格文本和错误的工具提示,而且在通过键盘选择单元格时也会显示。 由于这一变更,如果鼠标在 DataGridView 处于编辑模式时悬停在未设置 ToolTipText 属性的单元格上,不会引发 CellFormatting 事件 。 不引发该事件的原因是鼠标悬停的单元格的内容显示为工具提示,而不是显示在单元格中。

引入的版本

3.1

DataGridView 处于编辑模式时,对依赖 CellFormatting 事件的所有代码进行重构。

类别

Windows 窗体

受影响的 API

None


.NET Core 3.0

默认控件字体更改为 Segoe UI 9 pt

更改描述

在 .NET Framework 中,Control.DefaultFont 属性设置为 Microsoft Sans Serif 8 pt。 下图显示了使用默认字体的窗口。

.NET Framework 中的默认控件字体

从 .NET Core 3.0 开始,默认字体设置为 Segoe UI 9 pt(与 SystemFonts.MessageBoxFont 相同的字体)。 作为此更改的结果,窗体和控件的大小会增加约 27%,以适应新默认字体的更大大小。 例如:

.NET Core 中的默认控件字体

此更改是为了与 Windows 用户体验 (UX) 准则保持一致。

引入的版本

3.0

由于窗体和控件的大小改变,因此请确保应用程序能够正确呈现。

要保留原始字体,请将窗体的默认字体设置为 Microsoft Sans Serif 8 pt。 例如:

public MyForm()
{
    InitializeComponent();
    Font = new Font(new FontFamily("Microsoft Sans Serif"), 8f);
}

类别

  • Windows 窗体

受影响的 API

无。


FolderBrowserDialog 的现代化

.NET Core 的 Windows 窗体应用程序中的 FolderBrowserDialog 控件已更改。

更改描述

在 .NET Framework 中,Windows 窗体对 FolderBrowserDialog 控件使用以下对话框:

.NET Framework 中的 FolderBrowserDialogControl

在 .NET Core 3.0 中,Windows 窗体使用 Windows Vista 中引入的更新的基于 COM 的控件:

.NET Core 中的 FolderBrowserDialogControl

引入的版本

3.0

此对话框将自动升级。

如果希望保留原始对话框,请在显示对话框之前将 FolderBrowserDialog.AutoUpgradeEnabled 属性设置为 false,如以下代码片段所示:

var dialog = new FolderBrowserDialog();
dialog.AutoUpgradeEnabled = false;
dialog.ShowDialog();

类别

Windows 窗体

受影响的 API


已从一些 Windows 窗体类型中删除 SerializableAttribute

已从一些没有已知二进制序列化方案的 Windows 窗体类中删除 SerializableAttribute

更改描述

下列类型在 .NET Framework 中以 SerializableAttribute 进行修饰,但该属性已在 .NET Core 中删除:

从历史记录来看,此序列化机制存在严重的维护和安全性问题。 保证类型上持续具有 SerializableAttribute 意味着必须针对版本间的序列化更改以及可能出现的框架间序列化更改测试这些类型。 这使得很难发展这些类型且维护成本昂贵。 这些类型没有已知的二进制序列化方案,这在最大限度上消除了删除该属性带来的影响。

有关详细信息,请参阅二进制序列化

引入的版本

3.0

对于要标记为“可序列化”的类型,更新可能依赖它们的所有代码。

类别

Windows 窗体

受影响的 API


不支持 AllowUpdateChildControlIndexForTabControls 兼容性开关

Switch.System.Windows.Forms.AllowUpdateChildControlIndexForTabControls 兼容性开关在 .NET Framework 4.6 及更高版本上的 Windows 窗体中受支持,但在自 .NET Core 或 .NET 5.0 及更高版本中不受支持。

更改描述

在 .NET Framework 4.6 及更高版本中,选中选项卡会对其控件集合重新排序。 借助 Switch.System.Windows.Forms.AllowUpdateChildControlIndexForTabControls 兼容性开关,应用程序可在不需要此类重新排序时跳过此行为。

.NET Core 和 .NET 5.0 及更高版本中尚不支持 Switch.System.Windows.Forms.AllowUpdateChildControlIndexForTabControls 开关。

引入的版本

3.0

删除此开关。 此开关不受支持,且未提供替代功能。

类别

Windows 窗体

受影响的 API


不支持 DomainUpDown.UseLegacyScrolling 兼容性开关

已在 .NET Framework 4.7.1 中引入 Switch.System.Windows.Forms.DomainUpDown.UseLegacyScrolling 兼容性开关,但它在 .NET Core 或 .NET 5.0 及更高版本上的 Windows 窗体中尚不受支持。

更改描述

自 .NET Framework 4.7.1 起,开发人员可使用 Switch.System.Windows.Forms.DomainUpDown.UseLegacyScrolling 兼容性开关选择不执行独立 DomainUpDown.DownButton()DomainUpDown.UpButton() 操作。 该开关会还原旧行为,也就是说如果存在上下文文本,则忽略 DomainUpDown.UpButton()而且开发人员需要先在控件上执行 DomainUpDown.DownButton() 操作,然后才能执行 DomainUpDown.UpButton() 操作。 有关详细信息,请参阅 <AppContextSwitchOverrides> 元素

.NET Core 和 .NET 5.0 及更高版本中尚不支持 Switch.System.Windows.Forms.DomainUpDown.UseLegacyScrolling 开关。

引入的版本

3.0

删除此开关。 此开关不受支持,且未提供替代功能。

类别

Windows 窗体

受影响的 API


不支持 DoNotLoadLatestRichEditControl 兼容性开关

已在 .NET Framework 4.7.1 中引入 Switch.System.Windows.Forms.UseLegacyImages 兼容性开关,但它在 .NET Core 或 .NET 5.0 及更高版本上的 Windows 窗体中尚不受支持。

更改描述

在 .NET Framework 4.6.2 及更低版本中,RichTextBox 控件会实例化 Win32 RichEdit 控件 v3.0;而对于面向 .NET Framework 4.7.1 的应用程序,RichTextBox 控件会实例化 RichEdit v4.1(位于 msftedit.dll 中)。 已引入 Switch.System.Windows.Forms.DoNotLoadLatestRichEditControl 兼容性开关,使面向 .NET Framework 4.7.1 及更高版本的应用程序可选择不使用新的 RichEdit v4.1 控件而改用旧的 RichEdit v3 控件。

.NET Core 和 .NET 5.0 及更高版本中尚不支持 Switch.System.Windows.Forms.DoNotLoadLatestRichEditControl 开关。 仅支持 RichTextBox 控件的新版本。

引入的版本

3.0

删除此开关。 此开关不受支持,且未提供替代功能。

类别

Windows 窗体

受影响的 API


不支持 DoNotSupportSelectAllShortcutInMultilineTextBox 兼容性开关

已在 .NET Framework 4.6.1 中引入 Switch.System.Windows.Forms.DoNotSupportSelectAllShortcutInMultilineTextBox 兼容性开关,但它在 .NET Core 和 .NET 5.0 及更高版本上的 Windows 窗体中尚不受支持。

更改描述

自 .NET Framework 4.6.1 起,在 TextBox 控件中选择 Ctrl + A 快捷键会选中所有文本。 在 .NET Framework 4.6 及更低版本中,如果 Textbox.ShortcutsEnabledTextBox.Multiline 属性都设置为 true,则选择 Ctrl + A 快捷键没法选中全部文本。 为保留原始行为,已在 .NET Framework 4.6.1 中引入 Switch.System.Windows.Forms.DoNotSupportSelectAllShortcutInMultilineTextBox 兼容性开关。 有关更多信息,请参见TextBox.ProcessCmdKey

.NET Core 和 .NET 5.0 及更高版本中尚不支持 Switch.System.Windows.Forms.DoNotSupportSelectAllShortcutInMultilineTextBox 开关。

引入的版本

3.0

删除此开关。 此开关不受支持,且未提供替代功能。

类别

Windows 窗体

受影响的 API

  • None

不支持 DontSupportReentrantFilterMessage 兼容性开关

已在 .NET Framework 4.6.1 中引入 Switch.System.Windows.Forms.DontSupportReentrantFilterMessage 兼容性开关,但它在 .NET Core 和 .NET 5.0 及更高版本上的 Windows 窗体中尚不受支持。

更改描述

自 .NET Framework 4.6.1 起,Switch.System.Windows.Forms.DontSupportReentrantFilterMessage 兼容性开关可处理通过自定义 IMessageFilter.PreFilterMessage 实现调用 Application.FilterMessage 消息时可能引发的 IndexOutOfRangeException 异常。 有关详细信息,请参阅缓解:自定义 IMessageFilter.PreFilterMessage 实现

.NET Core 和 .NET 5.0 及更高版本中尚不支持 Switch.System.Windows.Forms.DontSupportReentrantFilterMessage 开关。

引入的版本

3.0

删除此开关。 此开关不受支持,且未提供替代功能。

类别

Windows 窗体

受影响的 API


不支持 EnableVisualStyleValidation 兼容性开关

.NET Core 或 .NET 5.0 及更高版本上的 Windows 窗体不支持 Switch.System.Windows.Forms.EnableVisualStyleValidation 兼容性开关。

更改描述

在 .NET Framework 中,Switch.System.Windows.Forms.EnableVisualStyleValidation 兼容性开关使得应用程序可选择不验证以数值格式提供的视觉样式。

.NET Core 和 .NET 5.0 及更高版本中尚不支持 Switch.System.Windows.Forms.EnableVisualStyleValidation 开关。

引入的版本

3.0

删除此开关。 此开关不受支持,且未提供替代功能。

类别

Windows 窗体

受影响的 API


不支持 UseLegacyContextMenuStripSourceControlValue 兼容性开关

已在 .NET Framework 4.7.2 中引入 Switch.System.Windows.Forms.UseLegacyContextMenuStripSourceControlValue 兼容性开关,但它在 .NET Core 或 .NET 5.0 及更高版本上的 Windows 窗体中尚不受支持。

更改描述

自 .NET Framework 4.7.2 起,开发人员可使用 Switch.System.Windows.Forms.UseLegacyContextMenuStripSourceControlValue 兼容性开关选择退出 ContextMenuStrip.SourceControl 属性的新行为 - 新行为是返回对源控件的引用。 该属性之前的行为是返回 null。 有关详细信息,请参阅 <AppContextSwitchOverrides> 元素

.NET Core 和 .NET 5.0 及更高版本中尚不支持 Switch.System.Windows.Forms.UseLegacyContextMenuStripSourceControlValue 开关。

引入的版本

3.0

删除此开关。 此开关不受支持,且未提供替代功能。

类别

Windows 窗体

受影响的 API


不支持 UseLegacyImages 兼容性开关

已在 .NET Framework 4.8 中引入 Switch.System.Windows.Forms.UseLegacyImages 兼容性开关,但它在 .NET Core 或 .NET 5.0 及更高版本上的 Windows 窗体中尚不受支持。

更改描述

自 .NET Framework 4.8 起,Switch.System.Windows.Forms.UseLegacyImages 兼容性开关会处理高 DPI 环境中 ClickOnce 方案内可能出现的图像缩放问题。 如果设置为 true,则用户可通过此开关在缩放比例设置为大于 100% 的高 DPI 显示器上还原旧的图像缩放行为。 有关详细信息,请参阅 GitHub 上的 .NET Framework 4.8 发行说明

.NET Core 和 .NET 5.0 及更高版本中尚不支持 Switch.System.Windows.Forms.UseLegacyImages 开关。

引入的版本

3.0

删除此开关。 此开关不受支持,且未提供替代功能。

类别

Windows 窗体

受影响的 API


请参阅