将路径作为字符串传递而不是使用 DirectoryInfo/FileInfo 的充分理由

发布于 2024-07-15 08:15:27 字数 204 浏览 4 评论 0原文

在我的新代码中,我使用字符串来传递目录路径或文件名。 相反,我使用 DirectoryInfo 和 FileInfo,因为它们似乎封装了很多信息。

我见过很多使用字符串传递目录信息的代码,然后它们在长的难以理解的语句中“拆分”、“mid”和“instr”,直到获得他们正在查找的目录部分。

有什么充分的理由将路径作为字符串传递吗?

In my new code I am not using strings to pass directory paths or file names. Instead I am using DirectoryInfo and FileInfo as they seem to encapsulate a lot of information.

I have seen a lot of code that uses strings to pass directory information then they "split" and "mid" and "instr" in long incomprehensible statements until they get the part of the directory they are looking for.

Is there any good reason to pass paths as strings?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

无所的.畏惧 2024-07-22 08:15:27

一般来说,我认为将信息保留在 FileInfo/DirectoryInfo 中更好。 这些类中有很多有用的功能,并且涉及很多安全性,因为它更容易检查文件是否存在,查看最初指定的文件等。

我(可能)通过的唯一地方如果路径要跨 AppDomain 或在进程之间传递等,则可以使用字符串形式的路径,而不是使用 FileInfo 和 DirectoryInfo。FileInfo

和 DirectoryInfo 都可以跨 AppDomain 边界正常工作(因为它们是可序列化的),但它们有一个在这种情况下,开销会增加很多。 如果事情来回频繁,可能会产生影响。

不过,在这种情况下,我会坚持使用 FileInfo 和 DirectoryInfo,除非我发现在分析过程中存在明显的问题,并且我正在尝试减少序列化数据量。 如果我没有遇到性能问题,我会坚持使用这些类,因为它们提供了很多安全性和功能。

In general, I think keeping the information in FileInfo/DirectoryInfo is better. There is a lot of useful functionality in these classes, as well as a lot of safety involved in that it's much easier to check for existence of a file, see the originally specified file, etc.

The only place where I would (potentially) pass a path as as a string instead of using FileInfo and DirectoryInfo would if the path was going to be passed across AppDomains or between processes, etc.

FileInfo and DirectoryInfo both work fine across AppDomain boundaries (since they're Serializable), but they have a fair amount more overhead in this situation. If things are going back and forth a lot, it could have an impact.

I would stick with FileInfo and DirectoryInfo in this case, though, unless I found that there was a noticeable problem during my profiling, and I was trying to reduce the amount of serialized data. If I didn't run into performance issues, I'd stick with using these classes, as they provide a lot of safety and functionality.

枕花眠 2024-07-22 08:15:27

如果您只需要一个路径,DirectoryInfoFileInfo 对于传递来说非常繁重。 我更关心“split and mid and instr”垃圾。 了解以下方法:

Path.GetFileName
路径.GetDirectoryName
路径.组合
等等...

顺便说一句,这些来自 System.IO.Path 类。

DirectoryInfo and FileInfo are awful heavy for passing around if all you need is a path. I'd be more concerned about the "split and mid and instr" junk. Learn the ways of:

Path.GetFileName
Path.GetDirectoryName
Path.Combine
etc...

Those are from the System.IO.Path class, btw.

流星番茄 2024-07-22 08:15:27

一旦路径位于应用程序中(即不在纯文本配置文件中),就没有充分的理由。

(我能想到的)它唯一有用的时候是与仅接受路径作为字符串的代码进行互操作时。

Once the path is in an application (i.e. not in a plain text configuration file), no, there isn't a good reason.

The only time (I can think of) it could be useful is when interoperating with code that only accepts paths as strings.

悲喜皆因你 2024-07-22 08:15:27

路径字符串和 FileInfo 之间有一个需要记住的显着区别,可以在下面的测试中进行总结:

FileInfo 反映文件实例化时的有关文件的信息 - 它可以被删除/修改并且 FileInfo 不会反映这一点。

[TestMethod]
        public void TestFileInfo()
        {
            var path = @"C:\Users\bjarmuz\Desktop\aybabtu.txt";
            File.WriteAllText(path, "All your base are belong to us!");
            var file = new FileInfo(path);

            Assert.IsTrue(file.Exists);
            File.Delete(file.FullName);
            Assert.IsTrue(file.Exists);
            Assert.IsFalse(File.Exists(file.FullName));
        }

  [TestMethod]
        public void TestFileInfo()
        {
            var path = @"C:\Users\bjarmuz\Desktop\aybabtu.txt";
            File.WriteAllText(path, "All your base are belong to us!");
            Thread.Sleep(1000);

            var file = new FileInfo(path);
            var date = DateTime.UtcNow;

            Assert.IsTrue(file.LastWriteTimeUtc< date);

            File.WriteAllText(path, "No!");
            Assert.IsTrue(File.GetLastWriteTimeUtc(file.FullName)> date);

            Assert.IsFalse(file.LastWriteTimeUtc > date);
        }

这可能会有些误导,如果您的代码传递 FileInfos 而不是字符串,您可能会看到属性的不正确结果,例如 ExistsLast[..]Time -如果您使用 File.Get[...]() 方法,则不会发生这种情况。

但是,另一方面,您也不应该依赖 File.Exists() 方法 - 因为可以在运行测试后立即创建/删除文件。 正确的方法是不执行此检查,而是接受它可以抛出 IO 异常(并准备好正确处理它)。 这篇精彩文章中的更多信息 https://blogs.msdn .microsoft.com/ericlippert/2008/09/10/veshing-exceptions/

此外,FileInfo/DirectoryInfo 的一个重要“优点”是它可以保护您的方法(以及方法使用者)免受以下情况的影响:

void SaveEntity(Entity theThing, string path)
{
    //now, based on the signature, you don't know whether you need file path or directory path

}

//void SaveEntity(Entity theThing, DirectoryInfo path) {}
//void SaveEntity(Entity theThing, FileInfo path) {}

One significant difference between path string and FileInfo to bear in mind, which can be summarized in the tests below:

A FileInfo reflects the info about the file as of when it was instantiated - it can be deleted/modified and the FileInfo won't reflect that.

[TestMethod]
        public void TestFileInfo()
        {
            var path = @"C:\Users\bjarmuz\Desktop\aybabtu.txt";
            File.WriteAllText(path, "All your base are belong to us!");
            var file = new FileInfo(path);

            Assert.IsTrue(file.Exists);
            File.Delete(file.FullName);
            Assert.IsTrue(file.Exists);
            Assert.IsFalse(File.Exists(file.FullName));
        }

  [TestMethod]
        public void TestFileInfo()
        {
            var path = @"C:\Users\bjarmuz\Desktop\aybabtu.txt";
            File.WriteAllText(path, "All your base are belong to us!");
            Thread.Sleep(1000);

            var file = new FileInfo(path);
            var date = DateTime.UtcNow;

            Assert.IsTrue(file.LastWriteTimeUtc< date);

            File.WriteAllText(path, "No!");
            Assert.IsTrue(File.GetLastWriteTimeUtc(file.FullName)> date);

            Assert.IsFalse(file.LastWriteTimeUtc > date);
        }

This can be somewhat misleading, and if your code passes around FileInfos instead of strings, you might see incorrect results for the properties such as Exists or Last[..]Time - which would not happen if you'd use the File.Get[...]() methods.

However, on the other hand, you should not rely on the File.Exists() method either - because the file can be created/deleted just after you run the tests. Proper way for that is to NOT do this check, and rather accept that it can throw the IO exception (and be ready to handle it properly). More info in this great article https://blogs.msdn.microsoft.com/ericlippert/2008/09/10/vexing-exceptions/

Also, a significant 'upside' of FileInfo/DirectoryInfo is that it protects your method (and the method consumers) from this:

void SaveEntity(Entity theThing, string path)
{
    //now, based on the signature, you don't know whether you need file path or directory path

}

//void SaveEntity(Entity theThing, DirectoryInfo path) {}
//void SaveEntity(Entity theThing, FileInfo path) {}
╭⌒浅淡时光〆 2024-07-22 08:15:27

我认为您确实需要一个类来封装文件或目录路径,而不是使用原始字符串并使用静态 System.IO.Path 类来操作它们。 但是,我认为 DirectoryInfo 和 FileInfo 不合适,因为它们似乎更多地用于进行文件/目录操作而不是路径操作。 如果您为路径操作创建自定义类,则可以提供更多用户友好的路径操作功能< /a>.

I think you do need a class to encapsulate a file or directory path, instead of using raw strings and manipulating them using the static System.IO.Path class. However, I don't find DirectoryInfo and FileInfo suitable, because they seem to be intended more for doing file/directory manipulations instead of path operations. If you make a custom class for path manipulation, you can provide more user friendly path manipulation functionality.

疯到世界奔溃 2024-07-22 08:15:27

我在将 FileInfo 传递到 DMZ 时遇到了问题。 据我所知 - 如果我错了请纠正我 - FileInfo 在反序列化时执行权限检查,这在 DMZ 中不起作用并导致“找不到路径”。 使用您的数据创建并传递自定义对象。

I've encountered problems when passing FileInfo to DMZ's. As far as I can see - correct me if i'm wrong - FileInfo performs a permission check when deserializing and that won't work from DMZ and result in 'path not found'. Create and pass a custom object with the data you instead.

垂暮老矣 2024-07-22 08:15:27

我找到了一个不使用其中任何一个的充分理由。
归根结底,路径是类型,通常通过字符串表示,但它本身不是字符串,它具有一些行为,如 在此视频中(只需检查第 60 秒后的几秒)

该视频本身为文件路径管理提供了一个很好的解决方案,对于您在路径上寻找的任何其他行为来说,这是一个良好的开始。

唯一的缺点是在极高的性能环境中会产生一些内存开销,但如果您没有创建数百个路径对象,则在大多数情况下没有理由不使用以下代码:

//This class provides all the rules for your application about how to handle a path as a value
public record FilePath
{
    public string Path { get; }
    
    public FilePath (string path) => 
        Path = 
            string.IsNullOrWhiteSpace (path) 
                ? throw new ArgumentException ("path cannot be null or empty") :
            System.IO.Path.GetInvalidPathChars().Intersect (path).Any()
                ? throw new ArgumentException ("Path contains illegal characters")
                : System.IO.Path.GetFullPath (path.Trim());
            
    public override string ToString() => Path;
    
    //Note on linux environments you would make it case sensitive
    public virtual bool Equals (FilePath? other) => 
        (Path).Equals (other?.Path, StringComparison.InvariantCultureIgnoreCase);

    public override int GetHashCode() => Path.ToLowerInvariant().GetHashCode();

    public static implicit operator FilePath (string name) => new FilePath (name);

    public FileInfo GetInfo() => new FileInfo (Path);

    public FilePath Combine (params string[] paths) =>
        System.IO.Path.Combine (paths.Prepend (Path).ToArray());
}

归功于 Joe Albahari,查看视频,了解有关 C# 的更多有趣内容。

LinQPad 7 源代码示例中提取的示例。

I found out a good reason to not use either.
At the end of the day a Path is Type that usually is represented though a string, but its not a string itself, it has some behaviour as explained in this video (Just check the few seconds after seconds 60).

That video itself provides a good solution for file path management that is a good start for whatever other behaviour you are looking for on a Path.

The only drawback would be some memory overhead on extremely high performance environments, but if you are not creating hundreds of path objects, there is no reason to not use the following code on most of cases:

//This class provides all the rules for your application about how to handle a path as a value
public record FilePath
{
    public string Path { get; }
    
    public FilePath (string path) => 
        Path = 
            string.IsNullOrWhiteSpace (path) 
                ? throw new ArgumentException ("path cannot be null or empty") :
            System.IO.Path.GetInvalidPathChars().Intersect (path).Any()
                ? throw new ArgumentException ("Path contains illegal characters")
                : System.IO.Path.GetFullPath (path.Trim());
            
    public override string ToString() => Path;
    
    //Note on linux environments you would make it case sensitive
    public virtual bool Equals (FilePath? other) => 
        (Path).Equals (other?.Path, StringComparison.InvariantCultureIgnoreCase);

    public override int GetHashCode() => Path.ToLowerInvariant().GetHashCode();

    public static implicit operator FilePath (string name) => new FilePath (name);

    public FileInfo GetInfo() => new FileInfo (Path);

    public FilePath Combine (params string[] paths) =>
        System.IO.Path.Combine (paths.Prepend (Path).ToArray());
}

Credits to Joe Albahari, checkout the video for more interesting things about C#.

Sample extracted from LinQPad 7 source code samples.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文