Summary
In v5, ShouldBeOneOf lost its params modifier, so the idiomatic actual.ShouldBeOneOf(a, b, c) call no longer compiles (CS1503). This is a source-breaking change for essentially every existing consumer of ShouldBeOneOf, and it isn't mentioned in the 4 → 5 migration guide.
Found while dogfooding 5.0.0-preview.2 against real repositories.
Details
v4.x signature (variadic):
public static void ShouldBeOneOf<T>(this T actual, params T[] expected)
v5 signature (src/Shouldly/ShouldlyExtensionMethods/ShouldBeRangeTestExtensions.cs) — params dropped, presumably to make room for the customMessage overloads:
public static void ShouldBeOneOf<T>(this T? actual, T[] expected, string? customMessage = null, ...)
public static void ShouldBeOneOf<T>(this T? actual, T[] expected, IEqualityComparer<T> comparer, string? customMessage = null, ...)
Because params is gone, any call that passes individual values fails:
result.ShouldBeOneOf(Status.A, Status.B, Status.C);
// error CS1503: Argument 2: cannot convert from 'Status' to 'Status[]'
A call site that already passes a T[] keeps working — only the individual-value form breaks.
Real-world impact
Confirmed source breaks across the repos we upgraded from 4.x:
- dotnet/msbuild — 3 sites (
MSBuildClient_Tests.cs:78, BuildManager_Tests.cs:4382/4383)
- JasperFx/Lamar (StructureMap.Testing) — 4 sites
- JasperFx/Wolverine — 2 sites (
TransportCompliance.cs:662/714)
ShouldBeOneOf(a, b, c) is the canonical usage, so the practical blast radius is large.
Workaround
Wrap the values in an array:
result.ShouldBeOneOf([Status.A, Status.B, Status.C]); // or new[] { ... } on C# < 12
Suggested fix
Add back a params overload alongside the customMessage overloads (e.g. keep ShouldBeOneOf<T>(this T actual, params T[] expected) and provide the message-carrying variants under a distinct shape), so existing variadic call sites keep compiling. Failing that, this should at least be called out prominently in the 4 → 5 migration guide.
Summary
In v5,
ShouldBeOneOflost itsparamsmodifier, so the idiomaticactual.ShouldBeOneOf(a, b, c)call no longer compiles (CS1503). This is a source-breaking change for essentially every existing consumer ofShouldBeOneOf, and it isn't mentioned in the 4 → 5 migration guide.Found while dogfooding
5.0.0-preview.2against real repositories.Details
v4.x signature (variadic):
v5 signature (
src/Shouldly/ShouldlyExtensionMethods/ShouldBeRangeTestExtensions.cs) —paramsdropped, presumably to make room for thecustomMessageoverloads:Because
paramsis gone, any call that passes individual values fails:A call site that already passes a
T[]keeps working — only the individual-value form breaks.Real-world impact
Confirmed source breaks across the repos we upgraded from 4.x:
MSBuildClient_Tests.cs:78,BuildManager_Tests.cs:4382/4383)TransportCompliance.cs:662/714)ShouldBeOneOf(a, b, c)is the canonical usage, so the practical blast radius is large.Workaround
Wrap the values in an array:
Suggested fix
Add back a
paramsoverload alongside thecustomMessageoverloads (e.g. keepShouldBeOneOf<T>(this T actual, params T[] expected)and provide the message-carrying variants under a distinct shape), so existing variadic call sites keep compiling. Failing that, this should at least be called out prominently in the 4 → 5 migration guide.