Hot Reload lets you modify/add to your source code while the application is running, either with debugger attached to the process (F5) or not attached (Ctrl+F5). Edit & Continue lets you modify/add to your source code in break-mode while debugging without having to restart your debugging session.
This document captures the current state. Potential future improvements in this area are tracked by #49001.
Definitions
- Variable Capturing is the mechanism in which the lambda/delegate which is defined inline is able to hold on to any variables within its lexical scope
- Scope is the region of program text within which it is possible to refer to the entity declared by the name without qualification of the name
- Debug statement is a span of instructions delimited by subsequent sequence points. Usually a debug statement corresponds to a language statement, but it might correspond to just a part of a language statement (e.g. an opening brace of a block statement), an expression (e.g. lambda body) or other contiguous syntax (base constructor call).
- Internal active statement is a debug statement that contains a return address of a stack frame.
- Leaf active debug statement is a debug statement that contains an IP (instruction pointer) of any thread.
Edit operation | Additional Info |
---|---|
Add methods, fields, constructors, properties, events, indexers, field and property initializers, nested types and top-level types (including delegates, enums, interfaces, abstract and generic types, and anonymous types) to an existing type | The existing type cannot be an interface. Adding or modifying enum members within an existing enum is not supported. |
Add and modify iterators, yield statements |
Changing a regular method to an iterator method is supported |
Add and modify async methods, await expressions |
Modifying await expressions wrapped inside other expressions (e.g. G(await F()); ) is not supported. Changing a regular method to async is supported. |
Add and modify operations with dynamic objects | - |
Add lambda expressions | Lambda expressions can only be added if they are static, access the “this” reference that has already been captured, or access captured variables from a single scope |
Modify generic code | Enabled in .NET 8 and Visual Studio 17.7 |
Modify lambda expressions | The following rules guarantee that the structure of the emitted closure tree will not change--thus ensuring that lambdas in the new body are mapped to the corresponding generated CLR methods that implemented their previous versions:
|
Add LINQ expressions | LINQ expressions contain implicitly-declared anonymous functions. This means the edit rules for lambdas and LINQ will be the same. |
Modify LINQ expressions | LINQ expressions contain implicitly-declared anonymous functions. This means the edit rules for lambdas and LINQ will be the same. |
Modifying async lambda and LINQ expressions in combination | You can edit various nested expressions provided that they otherwise satisfy the EnC rules |
Edit partial class | Enabled in VS 16.10 |
Edit Source Generated File | Enabled in VS 16.10. |
Add using directive | Enabled in VS 16.10. |
Deleting members other than fields | Enabled in VS 17.3 |
Renaming members other than fields | Enabled in VS 17.4 |
Rename method parameters | Enabled in VS 17.0 |
Modify method parameter types | Enabled in VS 17.4 |
Change return type of a method/event/property/operator/indexer | Enabled in VS 17.4 |
Add and modify custom attributes | Enabled in VS 17.0 |
Adding and modifying namespace declarations | Enabled in VS 17.3 |
Edit operation | Additional Info |
---|---|
Modify interfaces | - |
Add a method body such that an abstract method becomes non-abstract | - |
Add new abstract, virtual, or override member to a type | You CAN add a non-abstract member to an abstract type |
Add destructor to an existing type | - |
Modify a type parameter, base type, delegate type | - |
Modify a catch-block if it contains an active statement (leaf or internal) | - |
Modify a try-catch-finally block if the finally clause contains an active statement | - |
Delete types | - |
Edit a member referencing an embedded interop type | - |
Edit a member with On Error or Resume statements | Specific to Visual Basic |
Edit a member containing an Aggregate, Group By, Simple Join, or Group Join LINQ query clause | Specific to Visual Basic |
Edit in a solution containing projects that specify * in AssemblyVersionAttribute , e.g. [assembly: AssemblyVersion("1.0.*") ]. |
See workaround below. |
Hot Reload and Edit & Continue are not compatible with using *
in AssemblyVersionAttribute
value. Presence of *
in the version means that the compiler generates a new version
every build based on the current time. The build then produces non-reproducible, non-deterministic outputs (see Reproducible Builds).
It is thus highly recommended to use alternative versioning methods, such as Nerdbank.GitVersioning, that derive the assembly version from the HEAD commit SHA (for git repositories).
To enable generating commit SHA based assembly versions using
Nerdbank.GitVersioning
package, specify{ "assemblyVersion" : {"precision": "revision"} }
setting inversion.json
.
If you prefer to keep using *
in AssemblyVersionAttribute
it is recommended to use conditional compilation directive to only apply such version to Release builds like so:
#if DEBUG
[assembly: AssemblyVersion("1.0.0.0")]
#else
[assembly: AssemblyVersion("1.0.*")]
#endif