Skip to content

Add a DirectoryPath property to DirectoryNotFoundException to be consistent with FileNotFoundException #103468

@daiplusplus

Description

@daiplusplus

Background and motivation

The DirectoryNotFoundException type does not provide any way for the thrower to specify the actual directory path in a machine-readable way such that any downstream/consuming program code that catches the exception can isolate the directory-path; currently we're forced to try to parse the human-readable .Message property which, additionally, might be a localized string and thus impossible to reliably process under all circumstances, which is important in error-handling functions.

It's also inconsistent with how FileNotFoundException has a String FileName { get; } property.


I did search through all 7 pages of existing Issues in the runtime repo matching "DirectoryNotFoundException" - none of them are a request to add a directory-path property to the exception.

API Proposal

namespace System.IO;

public class DirectoryNotFoundException : IOException
{
    public DirectoryNotFoundException (string? message, string? directoryPath, Exception? innerException)
        : this(message: message, innerException: innerException)
    {
        this.DirectoryPath = directoryPath;
    }

    public DirectoryNotFoundException (string? message, string? directoryPath)
        : this(message: message)
    {
        this.DirectoryPath = directoryPath;
    }

    public string? DirectoryPath { get; }
}

API Usage

public static void ExampleMethodThatCopiesFilesAround(DirectoryInfo source, DirectoryInfo dest)
{
    if (!source.Exists) throw new DirectoryNotFoundException(message: "Source directory does not exist.", directoryPath: source.FullName);
    if (!dest.Exists) throw new DirectoryNotFoundException(message: "Destination directory does not exist.", directoryPath: dest.FullName);

    foreach (FileInfo fi in source.GetFiles())
    {
        // etc...
    }
}

//

using Microsoft.Extensions.Logging;

public void ConsumingMethodWithLogger()
{
    try
    {
        ExampleMethodThatCopiesFilesAround(source: foo, dest: bar);
    }
    catch (DirectoryNotFoundException dEx)
    {
        using (this.logger.BeginScope("DirectoryPath", dEx.DirectoryPath))
        {
            this.logger.LogError(exception: dEx, message: "Directory not found: {DirectoryPath}", dEx.DirectoryPath);
        }
    }
}

Alternative Designs

No response

Risks

This change involves only adding additional (and entirely optional and nullable) constructor overloads and properties.

It's possible that there exists user-code that subclasses DirectoryNotFoundException to add their own property for the missing directory's full-path, but I assume this wouldn't be an ABI breaking change because user subclasses would still be using a different class member "slot" (right?)

Metadata

Metadata

Assignees

Labels

api-approvedAPI was approved in API review, it can be implementedarea-System.IOhelp wanted[up-for-grabs] Good issue for external contributors

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions