After discussion on the mailing list and in the context of another bug, Dale King pointed out that the source of the problem is that a constraint expression is resolved by Assert.That on it's first use and a pointer to the resolved constraint is what is actually used. What we should do for a reusable constraint is to pre-resolve it and then save that pointer.
Note that the problem does not arise with simple constraints like Is.Null. It's only when the constraint has pending operators to be resolved - like Is.Not.Null - that we see the issue.
Requiring the user to resolve the constraint first seems like too much. The Resolve() method is an explicit interface implementation and so requires a cast for it even to be called. I'll experiment with a wrapper class that allows reuse and add some info about reuse to the docs.
After discussion on the mailing list and in the context of another bug, Dale King pointed out that the source of the problem is that a constraint expression is resolved by Assert.That on it's first use and a pointer to the resolved constraint is what is actually used. What we should do for a reusable constraint is to pre-resolve it and then save that pointer.
Note that the problem does not arise with simple constraints like Is.Null. It's only when the constraint has pending operators to be resolved - like Is.Not.Null - that we see the issue.
Requiring the user to resolve the constraint first seems like too much. The Resolve() method is an explicit interface implementation and so requires a cast for it even to be called. I'll experiment with a wrapper class that allows reuse and add some info about reuse to the docs.