Cached Entry Info
Overview
CachedEntryInfo is the library's replacement for FileInfo and DirectoryInfo. It captures a consistent snapshot of an entry's metadata in a single file system call. Two concrete types exist:
- CachedFileInfo: adds Length and IsReadOnly.
- CachedDirectoryInfo: narrows Path to IAbsoluteDirectoryPath.
The design fixes a handful of long-standing pitfalls in the System.IO equivalents.
What's Different
Existence-Guaranteed at Construction
You cannot obtain a CachedEntryInfo for a path that doesn't exist (or is the wrong type). Construction validates both up front and throws otherwise. There's no chance of holding an info object whose properties surprise-throw on first access.
Read-Only Properties
All properties are read-only. To change a file's attributes or timestamps, go through the Path property (which is a real path object) and then call Refresh to update the cached snapshot:
CachedFileInfo info = file.GetInfo();
info.Path.Attributes |= FileAttributes.Hidden;
info.Path.LastWriteTimeUtc = DateTime.UtcNow;
info.Refresh(); // re-query the file system
Type-Stable
If something on disk changes the entry from a file into a directory (or vice versa), Refresh throws IOException rather than silently returning misleading data.
Obtaining a CachedEntryInfo
From a Path
Call GetInfo on any IAbsolutePath. The static return type matches the path:
CachedFileInfo fileInfo = absoluteFilePath.GetInfo();
CachedDirectoryInfo dirInfo = absoluteDirectoryPath.GetInfo();
GetInfo throws if the entry doesn't exist or is the wrong type.
From a Path String (Type Not Known)
When you only have a string and don't statically know whether it refers to a file or a directory, use the Create factory:
CachedEntryInfo info = CachedEntryInfo.Create(pathString);
switch (info)
{
case CachedFileInfo file: /* handle file */ break;
case CachedDirectoryInfo dir: /* handle directory */ break;
}
The factory inspects the trailing segment of the string: a trailing separator, . or .. makes it directory-shaped and the result is a CachedDirectoryInfo; otherwise the path is probed and the correct concrete type is returned based on what actually exists on disk. If the entry is missing, FileNotFoundException (or DirectoryNotFoundException if its parent doesn't exist) is thrown. A directory-shaped path that resolves to a file is a hard error and throws IOException.
When you know the expected kind, prefer the typed shadows Create and Create. They have the same dispatch logic but throw IOException if the path resolves to the other kind:
CachedFileInfo file = CachedFileInfo.Create(pathString); // throws if path is a directory
CachedDirectoryInfo dir = CachedDirectoryInfo.Create(pathString); // throws if path is a file
From a Relative Sub-Path
GetInfo on an IAbsoluteDirectoryPath also accepts a relative path string. The overload combines the relative path with the directory and resolves the resulting entry in a single call, returning the correct concrete type:
CachedEntryInfo info = appBase.GetInfo("config/users.json");
// Trailing separator forces a directory:
CachedDirectoryInfo logsDir = (CachedDirectoryInfo)appBase.GetInfo("logs/");
Like Create, this overload uses the trailing segment to disambiguate file vs directory shape. Pass a PathFormat to control how the relative segment is parsed (see Combining and Navigating Paths).
From a System.IO Info Object
Use the ToCachedInfo extension methods to bridge from FileInfo / DirectoryInfo / FileSystemInfo:
FileInfo fi = new(@"C:\some\file.txt");
CachedFileInfo file = fi.ToCachedInfo();
FileSystemInfo fsi = picker.SelectedItem; // could be either
CachedEntryInfo info = fsi.ToCachedInfo(); // returns the right concrete type
From Enumeration
Use the *Info enumeration variants (see Searching and Enumeration) to get cached info objects directly without an extra stat per entry:
foreach (CachedFileInfo info in dir.GetChildFilesInfo("*.log"))
Console.WriteLine($"{info.Path.Name,-30} {info.Length,12:N0} {info.LastWriteTimeUtc:O}");
Properties
CachedEntryInfo (base):
- Path: the underlying IAbsolutePath.
- Attributes.
- CreationTime / CreationTimeUtc.
- LastAccessTime / LastAccessTimeUtc.
- LastWriteTime / LastWriteTimeUtc.
CachedFileInfo adds:
- Path narrowed to IAbsoluteFilePath.
- IsReadOnly.
- Length.
CachedDirectoryInfo adds only the narrowed Path to IAbsoluteDirectoryPath.
Refresh
Refresh re-queries the file system and updates the cached values. Call it whenever you suspect the underlying entry may have changed:
info.Refresh();
If the entry no longer exists or has changed type (a file became a directory, etc.), Refresh throws IOException.
When to Use Cached Info
Use cached info when you need multiple pieces of metadata for the same entry:
// Multiple property accesses on a path each touch the file system:
file.Length; // stat
file.LastWriteTimeUtc; // stat
file.Attributes; // stat
// One stat, multiple reads:
CachedFileInfo info = file.GetInfo();
info.Length;
info.LastWriteTimeUtc;
info.Attributes;
Use cached info during enumeration (Get*Info methods) whenever you'll read metadata from the results. The file system call that produced the entry already had the metadata, and the *Info variants surface it without a second round-trip.
When Not to Use Cached Info
For one-off checks where you only need a single property, going through the path directly is fine and slightly cheaper than constructing a snapshot:
if (file.LastWriteTimeUtc > cutoff) { /* ... */ }
Next Steps
- Searching and Enumeration: the
*Infovariants are designed to pair with this article. - Working with Files and Working with Directories: the path-side counterparts.