[API Proposal]: Add new constructors to FileSystemEnumerable and FileSystemEnumerator allowing a search pattern string to be provided
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
### Background and motivation
`DirectoryInfo.GetFiles` and related functions have a `searchPattern` string parameter for matching the file name. Historically, this matching was done in managed code (not at the OS-level), therefore it wasn't really necessary for `FileSystemEnumerator`/`FileSystemEnumerable` to take a search pattern string since matching could be done in the filter predicate. However, the OS (at least Windows), supports doing this filtering at the OS level, and this OS-level filtering is now implemented by https://github.com/dotnet/runtime/pull/122947. Thus it is now much faster to use `DirectoryInfo.GetFiles` in a scenario where a search pattern applies (e.g. filtering by a single file extension), even though `FileSystemEnumerator`/`FileSystemEnumerable` are meant to be the most performant methods. Therefore I propose they should accept a search pattern string. The implementation should be quite easy since there is now an internal constructor for `FileSystemEnumerator`/`FileSystemEnumerable` which accepts the search pattern (for Windows - for other OSes it would have to make use of the matching filter used by `DirectoryInfo`, which should also be quite straightforward).
For reference, see related discussion here - https://github.com/dotnet/runtime/discussions/127501.
### API Proposal
```csharp
namespace System.IO.Enumeration;
public abstract class FileSystemEnumerator : System.Runtime.ConstrainedExecution.CriticalFinalizerObject, System.Collections.Generic.IEnumerator
{
//Added searchPattern parameter to existing constructor
public FileSystemEnumerator(string directory, System.IO.EnumerationOptions? options = default, string? searchPattern = default);
}
public class FileSystemEnumerable : System.Collections.Generic.IEnumerable
{
//Added searchPattern parameter to existing constructor
public FileSystemEnumerable(string directory, System.IO.Enumeration.FileSystemEnumerable.FindTransform transform, System.IO.EnumerationOptions? options = default, string? searchPattern = default);
}
```
The searchPattern is in the same format as for [DirectoryInfo.GetFiles](https://learn.microsoft.com/en-us/dotnet/api/system.io.directoryinfo.getfiles?view=net-10.0).
### API Usage
```csharp
var enumeration = new FileSystemEnumerable(
directory: Path.GetTempPath(), // search Temp directory
transform: (ref FileSystemEntry entry) => entry.ToFullPath(), // map FileSystemEntry to string (see FileSystemEnumerable generic argument)
options: new EnumerationOptions()
{
RecurseSubdirectories = true
},
searchPattern: "*.tmp")
{
// The following predicate will be used to filter the file entries
ShouldIncludePredicate = (ref FileSystemEntry entry) => !entry.IsDirectory
};
```
This is taken from the [FileSystemEnumerable](https://learn.microsoft.com/en-us/dotnet/api/system.io.enumeration.filesystemenumerable-1?view=net-10.0) example and replaces the manual extension filter with a search pattern, which on Windows is now applied at the OS level.
### Alternative Designs
Could make the searchPattern a property of `FileSystemEnumerable`/`FileSystemEnumerator` instead.
### Risks
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.