Skip to content

FileInfo.Delete() does not update .Exists #31425

Closed

Description

@CodeAngry

FileInfo.Delete() does not update .Exists

So I just noticed:

	// this file exists
	var fi = new FileInfo(@"S:\Ome\File.path");
	// here fi.Exists == true
	fi.Delete();
	// still fi.Exists == true
	fi.Refresh();
	// finally fi.Exists == false

The code I wrote assumed Delete() changes .Exists and it was failing very unexpectedly. Checked the actual source code and found Delete() is implemented as:

	public override void Delete() => FileSystem.DeleteFile(FullPath);

instead of:

	public override void Delete()
	{
	    FileSystem.DeleteFile(FullPath);
	    Invalidate();
	}

Why is this simple operation not updating .Exists if it succeeds? On the other hand MoveTo() changes the fi object completely updating to the new path. So if you do a Delete() you need to followup with a Refresh() while a MoveTo() is good (even if it would have been better if Move() returned a new FileInfo with the new details instead of changing the current one).

Is this inconsistency by design or was it just overlooked?

Activity

  1. transferred this issue fromdotnet/coreon Nov 7, 2019
  2. stephentoub commented on Nov 7, 2019

    @stephentoub
    Member

    Is this inconsistency by design or was it just overlooked?

    https://docs.microsoft.com/en-us/dotnet/api/system.io.fileinfo.exists?view=netframework-4.8#remarks

    "When first called, FileInfo calls Refresh and caches information about the file. On subsequent calls, you must call Refresh to get the latest copy of the information."

  3. CodeAngry commented on Nov 8, 2019

    @CodeAngry
    Author

    I understand that but shouldn't Delete invalidate things. This is not about .Exists but .Delete. Move invalidates the data.

  4. wfurt commented on Nov 19, 2019

    @wfurt
    Member

    AFAIK Refresh is expected for compatibility reasons even if not really intuitive. Create() has similar behavior.

    cc: @JeremyKuhne

  5. AntonLapounov commented on Nov 19, 2019

    @AntonLapounov
    Contributor

    Then we must revert dotnet/corefx#40677 as well. We should either preserve compatibility or fix the issue consistently, not just one method of many.

  6. transferred this issue fromdotnet/corefxon Feb 1, 2020
  7. JeremyKuhne commented on Mar 3, 2020

    @JeremyKuhne
    Member

    I agree that updating the behavior consistently when users explicitly change state is the way to go. We need to document this breaking change, of course.

  8. added
    enhancementProduct code improvement that does NOT require public API changes/additions
    help wanted[up-for-grabs] Good issue for external contributors
    and removed
    untriagedNew issue has not been triaged by the area owner
    on Mar 3, 2020
  9. added this to the 5.0 milestone on Mar 3, 2020
  10. Jlalond commented on Mar 4, 2020

    @Jlalond
    Contributor

    @JeremyKuhne you can assign me to this if it's still available

  11. removed
    help wanted[up-for-grabs] Good issue for external contributors
    on Mar 4, 2020
  12. Jlalond commented on Mar 25, 2020

    @Jlalond
    Contributor

    Hey @JeremyKuhne / @carlossanlop to clarify, we're just calling refresh when we create a FileInfo, or delete, and the same for DirectoryInfo? @wfurt in the referenced issue you mentioned you had a way to more performantly do this other than a full refresh, do you still advise going down that route?

  13. wfurt commented on Mar 25, 2020

    @wfurt
    Member

    I would suggest to call Invalidate() as proposed above @Jlalond . If you do Refresh() we will be forced to do work immediately. With Invalidate() we would do work only if somebody asks again. I would expect that for example most developers assume file deleted after FileInfo.Delete() if it does not throw. I see no reason to do fstat just to verify that.

  14. Jlalond commented on Mar 25, 2020

    @Jlalond
    Contributor

    That's fair @wfurt, but should we call refresh upon create then?

  15. wfurt commented on Mar 25, 2020

    @wfurt
    Member

    Yes, I think so. We should be consistent and as @JeremyKuhne suggested we should update state for explicit actions. It seems like dotnet/corefx#40677 did it only when creating directories.
    I'm not sure how should we handle documentation @carlossanlop

  16. carlossanlop commented on Mar 25, 2020

    @carlossanlop
    Contributor

    I can take care of the documentation after this change is made. I also have to address dotnet/corefx#40677 as you requested.

  17. Jlalond commented on Mar 25, 2020

    @Jlalond
    Contributor

    Alright so refresh upon create and invalidate on delete. Thanks everyone

  18. wfurt commented on Mar 25, 2020

    @wfurt
    Member

    dotnet/corefx#40677 use Invalidate() for Create(). I think same logic can apply for creation. One can assume the object exist if Create() does not throw. We can defer work unless somebody explicitly asks.

  19. modified the milestones: 5.0.0, Future on Jun 18, 2020
  20. andrew-boyarshin commented on Jun 19, 2020

    @andrew-boyarshin
    Contributor

    Is this already fixed in #34229? If so, milestone change is incorrect and this issue should be closed.

  21. danmoseley commented on Jun 19, 2020

    @danmoseley
    Contributor

    Thank you yes @carlossanlop this it's fixed I think

  22. ghost locked as resolved and limited conversation to collaborators on Dec 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area-System.IOenhancementProduct code improvement that does NOT require public API changes/additions

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions