Skip to content

Conversation

@TimothyMakkison
Copy link
Contributor

Use return a shared static Task.FromResult(Passed) for successful assertions. This should be safe because AssertionResult is a readonly struct

Before

image

After

image

@thomhurst
Copy link
Owner

Summary

This PR introduces a shared static cached Task<AssertionResult> for successful assertions to reduce allocations in the hot path.

Critical Issues

CRITICAL: Static field initialization bug ⚠️

The new field in AssertionResult.cs:8:

internal static Task<AssertionResult> _passedTask = Task.FromResult(Passed);

This creates a static initialization order issue. The _passedTask field references the Passed property, but C# doesn't guarantee the order of static field initializers. Since Passed is a property (not a field), this should work, but it's fragile.

More importantly: The Passed property creates a new instance on every access:

public static AssertionResult Passed => new(true, string.Empty);

This means _passedTask is initialized with a Task<AssertionResult> containing one instance, but later direct uses of AssertionResult.Passed create different instances. While this works because AssertionResult is a readonly struct with value semantics, it's confusing.

Recommendation: Make the initialization explicit and safe:

internal static readonly Task<AssertionResult> _passedTask = Task.FromResult(new AssertionResult(true, string.Empty));

And add readonly modifier for thread safety (static fields should be readonly when immutable).


Minor: Field naming convention

The field _passedTask uses underscore prefix which typically indicates instance fields in C#. For static fields, consider s_passedTask or PassedTask (if keeping it internal).

Suggestions

  1. Consider readonly modifier: Since this is a shared static field accessed from multiple threads (assertions run concurrently), marking it readonly makes the immutability contract explicit and prevents accidental reassignment.

  2. Performance validation: The PR shows impressive allocation improvements in the screenshots. Consider adding a comment in the code explaining this optimization for future maintainers.

Verdict

⚠️ REQUEST CHANGES - Fix static initialization to avoid fragile dependency on property access order

@TimothyMakkison
Copy link
Contributor Author

CRITICAL: Static field initialization bug ⚠️

Since Passed is a property (not a field), this should work, but it's fragile.

Minor: Field naming convention

Name 'PassedTask' does not match rule 'camel_case_for_private_internal_fields'. Suggested name is '_passedTask'.

@thomhurst thomhurst merged commit 708b25b into thomhurst:main Jan 21, 2026
9 of 10 checks passed
This was referenced Jan 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants