JustDummies

Just dummies — but seriously powerful ones.

Documentation sections

JD028: InertDistinctness

PropertyValue
CategoryComposition (JustDummies.Composition)
Severity🟡 Warning
Enabled by defaultYes

Distinctness is declared over an element type that has no value equality. The default comparer falls back to reference equality, and every element the generator builds is a new instance — so the requirement is satisfied by construction and constrains nothing.

The collection can hold the same value several times, which is precisely what the declaration asks it not to.

Noncompliant

public sealed class Box {                          // neither Equals nor IEquatable
    public Box(int value) { Value = value; }
    public int Value { get; }
}

Any.ListOf(Any.Int32().Between(1, 2).As(v => new Box(v))).Distinct().WithCount(6)   // JD028

Measured on the library, that declaration returns six “distinct” boxes holding [1, 1, 1, 2, 1, 2] — green, every time.

Compliant

Give the element type value equality:

public sealed record Box(int Value);

Any.ListOf(Any.Int32().Between(1, 2).As(v => new Box(v))).Distinct().WithCount(6)
// AnyGenerationException: the element generator produced only 2 distinct value(s)

Now the declaration means something, and the impossible request is reported.

Or answer the equality question explicitly:

Any.ListOf(generator).Distinct(new BoxByValue())
Any.SetOf(generator, new BoxByValue())

Why the library cannot report this

From its side the requirement is met: the draws really are pairwise unequal under the comparer it was given, and there is nothing to complain about. Only the element type’s equality tells the inert case from the real one, and that is visible at the call site.

What it does not flag

  • A generator that hands back existing instances. Any.SetOf(Any.OneOf(first, second)) returns the very references it was given, so drawing the same member twice yields the same reference and distinctness binds exactly as asked.
  • An element type that is a value type, a record, an IEquatable<T> implementer, or that overrides Equals — anywhere in its base chain.
  • A non-sealed element type. A derived instance is free to add the equality the base lacks, and the rule only claims what it can prove.
  • A projection that may return a shared instance (As(v => Lookup(v))); only a chain that provably builds a new value here qualifies.
  • Any collection given an explicit comparer.

Read the source, or correct it there opens in a new tab· Mirrored from lib-v1.0.0-preview.6