perf: replace Any+IsAssignableTo predicate with 'is T' in ReflectionExtensions.HasAttribute (original) (raw)

TUnit.Core/Extensions/ReflectionExtensions.cs:64-66, 70-72:

return provider.GetCustomAttributes(inherit) .Any(x => x.GetType().IsAssignableTo(typeof(T)));

The fast path at line 59-62 already uses member.IsDefined(typeof(T), inherit). The fallback at :64 allocates:

  1. An object[] from GetCustomAttributes(inherit)
  2. The Any enumerator
  3. A delegate for the predicate
  4. x.GetType() per attribute (boxes returned RuntimeType)
  5. IsAssignableTo reflection call per attribute

Inline foreach with is T pattern match:

foreach (var x in provider.GetCustomAttributes(inherit)) { if (x is T) return true; } return false;

is T does a single VTable check, no GetType() boxing.

Same swap applies at :108:

return provider.GetCustomAttributes(typeof(T), inherit).Cast().ToArray();

GetCustomAttributes(typeof(T), inherit) already returns object[] whose runtime element type is T[]. Can use Array.ConvertAll or (T[])(object) array-covariance cast in some cases, avoiding the Cast<T> iterator + ToArray round-trip.

Why hot: Every attribute existence check on hot paths (skip/explicit/category lookups, hook discovery).
TFM: No gating.