hot reload 在 .net 6+ 中默认启用,但仅限 asp.net core、wpf(.net 7+)、winforms、maui(.net 7+)及部分控制台项目;不支持类库、.net framework、发布模式、program.cs 主入口或结构变更,需通过 dotnet watch run 或 vs 2022 热重载启动,且仅允许方法体内修改。

HotReload 在 .NET 6+ 中默认启用,但仅限特定项目类型
不是所有 C# 项目都能用 HotReload —— 它依赖于 dotnet watch + 支持热重载的运行时(.NET 6 及以上)+ 兼容的项目 SDK。控制台、ASP.NET Core Web API、Blazor Server、WPF(需 .NET 7+)等支持;传统 WinForms、.NET Framework 项目、或未启用 Microsoft.NET.Sdk.Web 等 SDK 的项目,直接不生效。
验证是否就绪:终端执行 dotnet --version 应 ≥ 6.0,且项目文件中包含类似 <targetframework>net6.0</targetframework> 或更高版本。
- ASP.NET Core 项目必须使用
WebApplication.CreateBuilder模式(即 Minimal Hosting Model),旧式Startup.cs+IWebHostBuilder不支持热重载 - 确保未手动禁用:
<enabledefaulthotreload>false</enabledefaulthotreload>这类配置要删掉 - Visual Studio 用户需确认已勾选「工具 → 选项 → 调试 → .NET Hot Reload → 启用 .NET Hot Reload」
dotnet watch run 是实际触发热重载的命令
VS 点“启动调试”(F5)时若没反应,大概率是因为没走 dotnet watch 流程。热重载不是 VS 自带的“编辑并继续(Edit and Continue)”,它不依赖调试器挂起,而是由 dotnet watch 监听文件变更并热应用。
正确做法是:终端进入项目根目录,执行 dotnet watch run(非 dotnet run)。此时控制台会显示 watch : Hot reload enabled.,之后修改 .cs 文件保存,几秒内就能看到效果(如 API 返回值变化、Razor 页面刷新)。
- 修改
.cshtml、.razor、.css、.js通常也支持,但行为因框架而异(Blazor Server 支持组件级热重载,Razor Pages 需刷新浏览器) - 不支持热重载的操作:
Program.cs顶层语句增删、新增/删除类、修改字段类型、改动泛型约束、调整partial类结构 —— 这些会触发完整重启 - VS 中按 Ctrl+F5(不调试启动)也能用
dotnet watch,但断点不会命中;F5(调试)在新版 VS 中已自动桥接dotnet watch,前提是项目配置正确
常见失败现象和对应检查点
改了代码没反应?控制台没打印 hot reload 日志?先看这些:
-
dotnet watch run报错MSB4057: The target "RunWithDotNetWatch" does not exist→ 项目 SDK 不兼容,检查是否用了Microsoft.NET.Sdk(控制台)或Microsoft.NET.Sdk.Web(Web),而非老式Microsoft.NET.Sdk.WindowsDesktop(WinForms/WPF 默认不带 watch 支持) - 修改后控制台提示
watch : Unable to apply hot reload updates→ 常见于改了构造函数签名、静态字段初始化、或调用了不支持热重载的 API(如某些反射操作) - Blazor Server 修改
.razor后页面白屏或报System.InvalidOperationException: Cannot process pending renders after the renderer is disposed→ 是热重载与 SignalR 连接状态冲突,关掉浏览器标签再重开,或加[CascadingParameter] public NavigationManager? Navigation { get; set; }避免在组件销毁后仍尝试导航 - VS 中 F5 启动却无热重载 → 检查项目属性 → “调试”页签 → “启用热重载”是否开启,且“启动行为”设为“可执行项目”而非“IIS Express”(后者不支持)
HotReload 的边界:它不是万能的“编辑并继续”
别指望它像调试器那样在断点处改局部变量、跳过某行、或重写整个方法体逻辑。它的设计目标是“快速迭代 UI 和业务逻辑微调”,不是“动态调试”。比如你正在调试一个循环,想临时把 i++ 改成 i += 2 —— 这类运行时状态相关的修改,dotnet watch 无法注入,会 fallback 到重启。
真正容易被忽略的是:热重载对程序集加载模型有强依赖。一旦某个类型被 JIT 编译且进入活跃调用栈(比如当前正停在某个方法里),该类型就无法被热替换。这也是为什么“改完立刻刷新页面”比“边调试边改”更可靠。
如果项目结构复杂(大量插件式加载、AssemblyLoadContext 自定义、IL 织入),HotReload 很可能被静默禁用 —— 此时 dotnet watch --verbose run 的输出里会出现 Hot reload disabled: custom assembly load context detected 这类提示,得换思路。











