diff --git a/src/Framework/ItemSpecModifiers.cs b/src/Framework/ItemSpecModifiers.cs
index aded6fb420a..f44d3c7d500 100644
--- a/src/Framework/ItemSpecModifiers.cs
+++ b/src/Framework/ItemSpecModifiers.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
@@ -53,34 +53,15 @@ internal static class ItemSpecModifiers
];
///
- ///
- /// Caches derivable item-spec modifier results for a single item spec.
- /// Stored on item instances (e.g., TaskItem, ProjectItemInstance.TaskItem)
- /// alongside the item spec, replacing the former string _fullPath field.
- ///
- ///
- /// Time-based modifiers (ModifiedTime, CreatedTime, AccessedTime) and RecursiveDir
- /// are intentionally excluded — time-based modifiers hit the file system and should
- /// not be cached, and RecursiveDir requires wildcard context that only the caller has.
- ///
- ///
- /// DefiningProject* modifiers are cached separately in a static shared cache
- /// () keyed by the defining project path,
- /// since many items share the same defining project.
- ///
+ /// Per-item cache for the FullPath modifier. Other derivable modifiers (RootDir,
+ /// Filename, Extension, RelativeDir, Directory) are intentionally NOT cached here
+ /// because TaskItem is a MarshalByRefObject on .NET Framework, and copying a
+ /// multi-field struct cross-AppDomain causes allocation regression in VS.
///
internal struct Cache
{
public string? FullPath;
- public string? RootDir;
- public string? Filename;
- public string? Extension;
- public string? RelativeDir;
- public string? Directory;
-
- ///
- /// Clears all cached values. Called when the item spec changes.
- ///
+
public void Clear()
=> this = default;
}
@@ -420,19 +401,19 @@ public static string GetItemSpecModifier(
return cache.FullPath ??= ComputeFullPath(currentDirectory, itemSpec);
case ItemSpecModifierKind.RootDir:
- return cache.RootDir ??= ComputeRootDir(cache.FullPath ??= ComputeFullPath(currentDirectory, itemSpec));
+ return ComputeRootDir(cache.FullPath ??= ComputeFullPath(currentDirectory, itemSpec));
case ItemSpecModifierKind.Filename:
- return cache.Filename ??= ComputeFilename(itemSpec);
+ return ComputeFilename(itemSpec);
case ItemSpecModifierKind.Extension:
- return cache.Extension ??= ComputeExtension(itemSpec);
+ return ComputeExtension(itemSpec);
case ItemSpecModifierKind.RelativeDir:
- return cache.RelativeDir ??= ComputeRelativeDir(itemSpec);
+ return ComputeRelativeDir(itemSpec);
case ItemSpecModifierKind.Directory:
- return cache.Directory ??= ComputeDirectory(cache.FullPath ??= ComputeFullPath(currentDirectory, itemSpec));
+ return ComputeDirectory(cache.FullPath ??= ComputeFullPath(currentDirectory, itemSpec));
case ItemSpecModifierKind.RecursiveDir:
return string.Empty;