From v5.x
Skipping v6 means every v6 change and every v7 change land together. This is the order to do them in.
This page exists because skipping a major is normal
Going from 5.x straight to 7.0.0 means the v6 changes and the v7 changes arrive in the same build. That is six silent changes rather than three, and they interact — so the order you work in matters more than it does on either single-version page.
One v6 change had a warning you will not get. WM1010 was the analyzer rule that warned about Option.Some accepting a value-type default. It shipped in 5.5.0 and v6 retired it, so it only ever protected people who happened to be on a 5.5.x release when they upgraded. If you are on 5.4 or earlier, that warning never existed for you.
Silent change 5 is that change. It is the one on this page with no tooling behind it at all.
Two steps it cannot do for you, both in step 1 of the prompt. Whether a null projection meant "absent" or was never supposed to happen is a domain question. So is whether an IsNone branch on a value-type option was standing in for "zero" — see Silent change 3. Expect the agent to bring both to you.
Read this first
Six changes keep compiling and change what your code does. Three came in v6 and three in v7.
Everything else breaks the build.
Do it in this order
Work through the v6 page and then the v7 page, rather than reading both at once. Two reasons, both practical.
The v6 async changes come first because the v7 changes sit on top of them. v6 made every async extension return ValueTask and moved async factories to TryAsync. The v7 WM2022 rule and the null-projection guard both describe chains you will have rewritten by then, so doing v6 first means you touch each chain once.
The loud v7 changes will hide the loud v6 ones. CS0234 on a removed extension class is a declaration-phase error, so it stops the compiler reporting anything in the body of every file that has the using. Land v6's loud changes, get a green build, then upgrade to 7.0.0.
Read v5.x to v6.x in full and do its silent changes. These are the ones with no compiler help, and they are the reason this page exists.
Upgrade to 6.x and get a clean build. Do not skip this. A single intermediate build separates two sets of diagnostics that are hard to tell apart in one pile.
Read v6.x to v7.0.0 and do its three silent changes.
Upgrade to
7.0.0and work the diagnostics. Build twice — see Diagnostics that mask other diagnostics.
If you cannot ship an intermediate 6.x build, the agent prompt handles both sets in one pass and reports them separately. It is a worse position to be in, not an equal one.
The three v6 silent changes, in brief
Full detail on v5.x to v6.x. This is enough to know whether they apply to you.
Silent change 1: Try with an async factory
Option.Try and Result.Try given an async factory return before the factory has finished, so nothing is caught. Use TryAsync.
WM1011 reports every one of these, as a warning, so this is the one v6 silent change your build will actually mention. Do not suppress it.
See Silent change 1.
Silent change 2: cancellation propagates
From 6.0.0 an OperationCanceledException is no longer converted into a None or an Err. It propagates to your caller.
Prefer that. If you genuinely relied on the old behaviour, opt back in:
Note the modern spelling — in 7.0.0 the Use… methods are on a builder, and the inferred lambda parameter above is what makes this line identical in both versions.
See Silent change 2.
Silent change 3: Option.Some accepts value-type defaults
Option.Some(0) returns a Some where 5.x threw, and Option<int> x = 0; gave you a None in 5.x and a Some(0) in 6.x.
This is the change with no tooling behind it for anyone below 5.5.0, and no tooling at all from 6.0.0 onward. Every IsNone branch on a value-type option has to be read by someone who knows whether it was standing in for zero.
See Silent change 3 on the v6 page.
The loud changes from both versions
Rather than repeat two tables, here is where each list lives:
v6's loud changes —
ValueTaskeverywhere,FlatMapremoved, deriving fromOptionorResultno longer allowed. On v5.x to v6.x.v7's loud changes — implicit conversions removed, configuration moved to a builder, extension classes collapsed, five obsolete members gone, parameter renames, and
TryAsyncandCollectAsyncreturningValueTask. On v6.x to v7.0.0, and as a reference table with diagnostics on Every v7 break.
Two of v6's loud changes are worth flagging here because they multiply on this path:
.AsTask() sites come from both versions. v6 moved the async extensions to ValueTask; v7 moved TryAsync and CollectAsync too. Coming from 5.x you cannot tell the two apart from the diagnostic, and you do not need to — treat every CS0029 between Task and ValueTask the same way. Prefer changing the declared type or awaiting the value; .AsTask() allocates.
FlatMap and the removed extension classes overlap. A call written as FlatMapExtensions.FlatMap(...) breaks twice — once because the method was renamed to AndThen in v6, and once because the class is gone in v7. Rename first, then drop the qualifier.
Analyzer rules across both versions
Delete .editorconfig entries and #pragma directives for every retired id. None of them is reused, so a stale entry neither errors nor warns — it simply does nothing, which is worse, because it reads as though something is configured.
v6.0.0
WM1004, WM1007, WM1009, WM1010, WM2014
v7.0.0
WM2010
Added across the two versions: WM1011, WM2015, WM2016, WM2017 and more in v6 — see v5.x to v6.x — and WM2022 in v7.
Everything on one page
Try with an async factory
v6
No, but WM1011 warns
Use TryAsync
Cancellation propagates
v6
No
Handle it, or UseCancellationAsFailure
Option.Some accepts value-type defaults
v6
No
Read every IsNone branch on a value type
Async extensions return ValueTask
v6
Yes
Change the declared type or await it
FlatMap removed
v6
Yes
Rename to AndThen
Deriving from Option or Result
v6
Yes
Compose rather than derive
A projection returning null throws
v7
No
AndThen with Option.FromNullable
AndThen rejects a null monad
v7
No
Return None or an Err
A scope disposed out of order
v7
No
Use using
Implicit conversions removed
v7
Yes
Take the code fix on CS0029 / CS1503
Configuration moved to a builder
v7
Yes, for explicit types only
Let the lambda parameter infer
Extension classes collapsed
v7
Yes
Drop the using static
Five obsolete members removed
v7
Yes
See the v7 page
Parameter renames
v7
Yes, for named arguments only
Take the code fix on CS1739
TryAsync and CollectAsync return ValueTask
v7
Yes, if you name the type
Change the declared type, or add .AsTask()
Last updated
Was this helpful?