diff --git a/src/Adapter/MSTestAdapter.PlatformServices/Discovery/AssemblyEnumerator.cs b/src/Adapter/MSTestAdapter.PlatformServices/Discovery/AssemblyEnumerator.cs index 89bf1c82ed..efdb766f24 100644 --- a/src/Adapter/MSTestAdapter.PlatformServices/Discovery/AssemblyEnumerator.cs +++ b/src/Adapter/MSTestAdapter.PlatformServices/Discovery/AssemblyEnumerator.cs @@ -289,12 +289,14 @@ private static bool TryUnfoldITestDataSource(ITestDataSource dataSource, UnitTes var discoveredTests = new List(); bool dataSourceHasData = false; + // PERF: Hoist outside the loop — MethodInfo.GetParameters() returns a fresh array copy on each + // call (CLR safety guarantee), so calling it per row allocates N identical arrays for N data rows. + ParameterInfo[] parameters = methodInfo.GetParameters(); foreach (object?[] dataOrTestDataRow in dataEnumerable) { dataSourceHasData = true; object?[] d = dataOrTestDataRow; - ParameterInfo[] parameters = methodInfo.GetParameters(); // The effective ignore message for this row is the row-level ignore message (from // TestDataRow), falling back to the whole-source ignore message. It must be diff --git a/src/Adapter/MSTestAdapter.PlatformServices/Execution/TestMethodInfo.cs b/src/Adapter/MSTestAdapter.PlatformServices/Execution/TestMethodInfo.cs index 165a49355d..df0879e8cb 100644 --- a/src/Adapter/MSTestAdapter.PlatformServices/Execution/TestMethodInfo.cs +++ b/src/Adapter/MSTestAdapter.PlatformServices/Execution/TestMethodInfo.cs @@ -60,7 +60,17 @@ internal ITestContext TestContext /// /// Gets the parameter types of the test method. /// - public ParameterInfo[] ParameterTypes => MethodInfo.GetParameters(); + /// + /// Lazy-cached: MethodInfo.GetParameters() returns a fresh array copy on every call + /// (CLR safety guarantee), so caching avoids N redundant copies for data-driven tests with N rows. + /// This cached array is shared across internal call sites and MUST NOT be mutated. The explicit + /// implementation hands external consumers a fresh copy to + /// preserve the previous "fresh array per call" behavior and protect the cache from mutation. + /// + public ParameterInfo[] ParameterTypes => field ??= MethodInfo.GetParameters(); + + /// + ParameterInfo[] ITestMethod.ParameterTypes => (ParameterInfo[])ParameterTypes.Clone(); /// /// Gets the return type of the test method.