Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ internal partial class TestMethodInfo

internal object?[] ResolveArguments(object?[] arguments)
{
// Use the cached ParameterTypes property rather than calling MethodInfo.GetParameters()
// (which allocates a fresh ParameterInfo[] on every call). ResolveArguments only reads the
// array, so sharing the cached instance is safe.
ParameterInfo[] parametersInfo = ParameterTypes;
int requiredParameterCount = 0;
bool hasParamsValue = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,22 @@ public ReflectionTestMethodInfo(MethodInfo methodInfo, string? displayName)

public override MethodImplAttributes GetMethodImplementationFlags() => _methodInfo.GetMethodImplementationFlags();

/// <summary>
/// Returns the parameters of the wrapped method, caching the array across calls.
/// </summary>
/// <returns>The cached <see cref="ParameterInfo"/> array of the wrapped method.</returns>
/// <remarks>
/// <c>MethodInfo.GetParameters()</c> allocates a fresh <see cref="ParameterInfo"/> array on
/// every call (a CLR safety guarantee). The wrapped <see cref="MethodInfo"/> is immutable, so the
/// array is cached and shared across callers of this wrapper (e.g. display-name computation for every
/// data-driven row) to avoid that per-call allocation.
/// <para>
/// Because the same instance is handed out to every caller, the returned array MUST be treated as
/// read-only. Mutating it (including callers such as user-provided
/// <c>ITestDataSource.GetDisplayName</c> implementations) would corrupt the cache for all subsequent
/// callers.
/// </para>
/// </remarks>
public override ParameterInfo[] GetParameters() => _parameters ??= _methodInfo.GetParameters();
Comment thread
Evangelink marked this conversation as resolved.

public override object? Invoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) => _methodInfo.Invoke(obj, invokeAttr, binder, parameters, culture);
Expand Down