Skip to content

System.IO.FileInfo .Exists and .Length inconsistencies between Open and Create #117709

@vpenades

Description

@vpenades

Description

It seems there's a recurring issue with System.IO.FileInfo internal state, which has been debated here: #31425

To recap:

  • An explicit .Refresh() is required after some operations to update the state of the FileInfo.
  • Some operations internally call Invalidate() so any subsequent status check will trigger a lazy Refresh().
  • Some other operations do not call Invalidate() leading to misleading behavior about when is required to call Refresh and when is not.

One such example of inconsistent behavior I found is this:

var finfo = new System.IO.FileInfo("some path");

var writeStream1 = finfo.Create(); // this DOES call Invalidate.

var writeStream2 = finfo.Open(FileMode.Create); // this does NOT call invalidate

Taking into account that Create() and Open(FileMode.Create) are roughly equivalent, the fact that one calls invalidate and the other one does not it's plain wrong.

Given that this is a recurring issue, I would suggest the following API changes:

  • A comprehesive review of the APIs, ensuring that all methods that change the state do call Invalidate().
  • Add a new method called Refresh(bool immediate), where:
    • immediate = true would refresh the state immediately (current behavior)
    • immediate = false would call Invalidate.
  • Make Refresh() => Refresh(false);

This will change the default behavior of Refresh() from immediately changing the state to lazily changing it, preventing degraded performance when developers compulsively call .Refresh();

Reproduction Steps

var finfo = new System.IO.FileInfo("some path");

var writeStream2 = finfo.Open(FileMode.Create);
// write some bytes
writeStream2.Dispose();

// finfo.Exists is false, length is zero, but it should be true and length correctly set.

var writeStream1 = finfo.Create();
// write some bytes
writeStream1.Dispose();

// finfo.Exists is true and length is correct.

Expected behavior

All methods that alter the state of FileInfo (and DirectoryInfo) should call Invalidate().

Actual behavior

Some methods call Invalidate() some others do not, leading to misleading behavior, and forcing developers to call .Refresh() compulsively.

Regression?

No response

Known Workarounds

Calling .Refresh() compulsively, which leads to degraded performance.

Configuration

Net 8, windows

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-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