| Property | Value |
|---|---|
| Category | Constraints (JustDummies.Constraints) |
| Severity | 🟠 Warning |
| Enabled by default | Yes |
Any.Enum<TEnum>() only ever yields a value TEnum defines: one of its declared members, or — on a [Flags] enum, where OneOf accepts a combination on its own account — an OR of declared members. It never invents an undeclared numeric value, even though the CLR would let you write one.
Naming a value outside that is not a narrowing that happens to be empty, it is a category error. An exclusion that removes every value left to draw is the same error from the other side.
Noncompliant
Any.Enum<Permissions>().OneOf((Permissions)16) // no OR of declared members produces 16
Any.Enum<Day>().OneOf((Day)99) // not a declared member at all
Any.Enum<Day>().OneOf((Day)3) // Day never said its members combine
Any.Enum<Day>().Except(Day.Mon, Day.Tue) // nothing remains to draw
Compliant
Any.Enum<Permissions>().OneOf(Permissions.Read | Permissions.Write) // writing a combination is asking for one
Any.Enum<Permissions>().AllowingCombinations() // a plain draw ranges over them once asked
Any.Enum<Permissions>().OneOf(Permissions.Read, Permissions.Write)
Any.Enum<Day>().Except(Day.Mon)
Why it is separate from the other constraint rules
Its domain is metadata — what the type declares — rather than interval arithmetic, and its mistake has its own teachable model: a value the type does not define is not a narrowing that happens to be empty, it is a category error. That is also what tells the rule where to stop. [Flags] is metadata saying the members combine, so Read | Write is a value the type defines without ever declaring it — and the rule follows the generator there rather than reading “declared” off the member list alone.
What it does not flag
- A combination of declared members named in
OneOfon a[Flags]enum — withAllowingCombinations(), without it, in either order. An allow-list is the pool, so writing a combination in one is asking for that exact value, and the generator draws it. - Any constraint once
AllowingCombinations()is declared — including an exclusion that removes every declared member. That widens the universe to the OR-closure of the declared members, which no longer matches a declared value one for one, so the rule stands down rather than approximate it:Except(Read, Write)beside it still leavesRead | Writeto draw, and the generator does draw it. - An exclusion that removes every declared member while the allow-list names a value none of the exclusions carries. What decides is whether anything the caller allowed survives, not whether the declared set was emptied.
- An exclusion that removes every declared member while the allow-list holds an entry the rule cannot read — a variable, a field, anything but a constant. An allow-list is the pool, so an unreadable entry is a pool the rule cannot decide rather than an absent one, and on a
[Flags]enum it may hold a combination no exclusion names. - A generic helper whose type argument is an unsubstituted type parameter — there is no enum to reason about, and the rule bails rather than guess.
- A non-constant value, or a partial exclusion that leaves at least one member.
- A conflict-asserting negative test.