Context
BrilliantMessaging is preparing to consume a curated, public single-file export produced by Light.GuardClauses.SourceCodeTransformation for netstandard2.0.
An inventory of its production guard clauses found that most cases already map cleanly to Light.GuardClauses. The following gaps are reusable enough to consider adding upstream. The usage counts below come from the current BrilliantMessaging code base and are intended to show concrete demand, not to prescribe the final API.
Strong candidates
1. Object-disposed condition
BrilliantMessaging has five explicit disposal guards. The closest current expression is a generic boolean assertion with an exception factory, which obscures the intent.
A dedicated condition guard analogous to Check.InvalidOperation would make the call site explicit while remaining usable on netstandard2.0:
Check.ObjectDisposed(isDisposed, objectName, message);
Expected behavior: throw ObjectDisposedException only when the condition is true. The exact object-name and custom-exception-factory overloads should follow existing library conventions.
2. Parseable URI string, including relative-or-absolute references
BrilliantMessaging validates a URI supplied as a string and accepts UriKind.RelativeOrAbsolute. Existing URI assertions operate on Uri instances, so callers must currently write Uri.TryCreate logic themselves.
Potential shape:
value.MustBeUri(UriKind.RelativeOrAbsolute);
Open design question: return the original string for fluent argument validation, or return the parsed Uri. Supporting an explicit UriKind is more general than a dedicated URI-reference-only assertion and could also cover absolute and relative inputs.
3. Throwing type-assignability assertion
BrilliantMessaging has six guards that reject a Type unless it is assignable to a required base type or interface. Light.GuardClauses currently has useful predicates such as IsOrImplements, but no direct throwing assertion for this relationship.
Potential shapes:
type.MustBeAssignableTo(requiredType);
type.MustImplement(requiredInterface);
MustBeAssignableTo is the more general primitive and should use the same semantics as Type.IsAssignableFrom, with a clearly documented direction. A custom exception-factory overload would be valuable because frameworks often need a domain-specific configuration exception.
4. Concrete-class assertion
BrilliantMessaging has three guards requiring a handler type to be a class that is not abstract.
Potential shape:
type.MustBeConcreteClass();
This should reject null, interfaces, abstract classes, and non-class types. It composes naturally with MustBeAssignableTo when both constraints are required.
5. MustBePositive parity for older target frameworks
The generic INumber<T> overload covers additional numeric types on .NET 8 and later, but a source export targeting netstandard2.0 only receives the concrete overloads. BrilliantMessaging has seven byte or ushort positive-value guards and must fall back to MustBeGreaterThan(0).
Add concrete MustBePositive overloads for the integral types not covered by the generic implementation on older targets, at minimum byte and ushort. Ideally, review the complete signed and unsigned integral matrix (sbyte, byte, short, ushort, uint, and ulong) for symmetry. Default and custom-exception-factory overloads should remain consistent with the existing numeric assertions.
Lower-priority candidates
These appeared in BrilliantMessaging, but may be better implemented in its own public partial Check class unless broader use cases emerge.
6. Positive timeout or infinite sentinel
Two guards accept either a positive TimeSpan or Timeout.InfiniteTimeSpan.
Potential shape:
timeout.MustBePositiveOrInfiniteTimeout();
This encodes a standard .NET timeout convention and may be generally useful, but it is narrower than the candidates above.
7. Exactly one value supplied
Two guards require exactly one of a routing-key string and a routing-key factory to be present.
A general xor/presence assertion is possible, but a readable, type-safe API is not obvious. The current recommendation is to keep this as a BrilliantMessaging-specific guard rather than add a generic boolean combinator to Light.GuardClauses.
Source transformation requirements
Any accepted assertion should be selectable through AssertionWhitelist, bring along only its required exception/factory dependencies, and preserve the existing per-assertion option for custom exception-factory overloads. The motivating consumer exports public code for netstandard2.0 under its own namespace.
Proposed scope
Context
BrilliantMessaging is preparing to consume a curated, public single-file export produced by
Light.GuardClauses.SourceCodeTransformationfornetstandard2.0.An inventory of its production guard clauses found that most cases already map cleanly to Light.GuardClauses. The following gaps are reusable enough to consider adding upstream. The usage counts below come from the current BrilliantMessaging code base and are intended to show concrete demand, not to prescribe the final API.
Strong candidates
1. Object-disposed condition
BrilliantMessaging has five explicit disposal guards. The closest current expression is a generic boolean assertion with an exception factory, which obscures the intent.
A dedicated condition guard analogous to
Check.InvalidOperationwould make the call site explicit while remaining usable onnetstandard2.0:Expected behavior: throw
ObjectDisposedExceptiononly when the condition istrue. The exact object-name and custom-exception-factory overloads should follow existing library conventions.2. Parseable URI string, including relative-or-absolute references
BrilliantMessaging validates a URI supplied as a string and accepts
UriKind.RelativeOrAbsolute. Existing URI assertions operate onUriinstances, so callers must currently writeUri.TryCreatelogic themselves.Potential shape:
Open design question: return the original
stringfor fluent argument validation, or return the parsedUri. Supporting an explicitUriKindis more general than a dedicated URI-reference-only assertion and could also cover absolute and relative inputs.3. Throwing type-assignability assertion
BrilliantMessaging has six guards that reject a
Typeunless it is assignable to a required base type or interface. Light.GuardClauses currently has useful predicates such asIsOrImplements, but no direct throwing assertion for this relationship.Potential shapes:
MustBeAssignableTois the more general primitive and should use the same semantics asType.IsAssignableFrom, with a clearly documented direction. A custom exception-factory overload would be valuable because frameworks often need a domain-specific configuration exception.4. Concrete-class assertion
BrilliantMessaging has three guards requiring a handler type to be a class that is not abstract.
Potential shape:
This should reject null, interfaces, abstract classes, and non-class types. It composes naturally with
MustBeAssignableTowhen both constraints are required.5.
MustBePositiveparity for older target frameworksThe generic
INumber<T>overload covers additional numeric types on .NET 8 and later, but a source export targetingnetstandard2.0only receives the concrete overloads. BrilliantMessaging has sevenbyteorushortpositive-value guards and must fall back toMustBeGreaterThan(0).Add concrete
MustBePositiveoverloads for the integral types not covered by the generic implementation on older targets, at minimumbyteandushort. Ideally, review the complete signed and unsigned integral matrix (sbyte,byte,short,ushort,uint, andulong) for symmetry. Default and custom-exception-factory overloads should remain consistent with the existing numeric assertions.Lower-priority candidates
These appeared in BrilliantMessaging, but may be better implemented in its own public partial
Checkclass unless broader use cases emerge.6. Positive timeout or infinite sentinel
Two guards accept either a positive
TimeSpanorTimeout.InfiniteTimeSpan.Potential shape:
This encodes a standard .NET timeout convention and may be generally useful, but it is narrower than the candidates above.
7. Exactly one value supplied
Two guards require exactly one of a routing-key string and a routing-key factory to be present.
A general xor/presence assertion is possible, but a readable, type-safe API is not obvious. The current recommendation is to keep this as a BrilliantMessaging-specific guard rather than add a generic boolean combinator to Light.GuardClauses.
Source transformation requirements
Any accepted assertion should be selectable through
AssertionWhitelist, bring along only its required exception/factory dependencies, and preserve the existing per-assertion option for custom exception-factory overloads. The motivating consumer exports public code fornetstandard2.0under its own namespace.Proposed scope
ObjectDisposed.UriKind.MustBeAssignableToand decide whetherMustImplementadds enough value as a convenience assertion.MustBeConcreteClass.MustBePositiveoverloads for older targets.