【问题标题】:Good reasons to pass paths as strings instead of using DirectoryInfo/FileInfo将路径作为字符串传递而不是使用 DirectoryInfo/FileInfo 的充分理由
【发布时间】:2010-10-14 14:48:50
【问题描述】:

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

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

是否有充分的理由将路径作为字符串传递?

【问题讨论】:

    标签: .net string directory


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      DirectoryInfoFileInfo 如果您只需要一条路径,那么在四处走走就太重了。我会更关心“分裂和中间和instr”的垃圾。了解以下方法:

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

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

      【讨论】:

      • 请记住,当您将实例传递给函数时,它传递的是引用的副本,而不是整个对象的副本!所以你真正传递的只是一个指针的副本......
      • 我认为问题不在于传递了多少字节,而在于使用 FileInfo/DirectoryInfo 的开销,它必须以各种方式探测文件以缓存有关它的信息。
      【解决方案3】:

      要记住路径字符串和 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 - 如果您使用 @987654325,则不会发生这种情况@方法。

      但是,另一方面,您也不应该依赖 File.Exists() 方法 - 因为可以在运行测试后立即创建/删除文件。正确的方法是不要做这个检查,而是接受它可以抛出 IO 异常(并准备好正确处理它)。这篇很棒的文章中的更多信息https://blogs.msdn.microsoft.com/ericlippert/2008/09/10/vexing-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) {}
      

      【讨论】:

        【解决方案4】:

        我认为您确实需要一个类来封装文件或目录路径,而不是使用原始字符串并使用静态 System.IO.Path 类来操作它们。但是,I don't find DirectoryInfo and FileInfo suitable,因为它们似乎更多地用于执行文件/目录操作而不是路径操作。如果您为路径操作制作自定义类,您可以提供more user friendly path manipulation functionality

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            【解决方案6】:

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

            如果路径要跨 AppDomains 或在进程之间传递等,我将(可能)将路径作为字符串传递而不是使用 FileInfo 和 DirectoryInfo 的唯一地方。

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

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

            【讨论】:

            • 请注意,如果文件已更改其存在或修改了时间戳,则需要创建新的 FileInfo/DirectoryInfo。
            猜你喜欢
            • 1970-01-01
            • 2010-11-26
            • 2011-08-30
            • 2020-10-31
            • 2014-06-26
            • 1970-01-01
            • 1970-01-01
            • 2019-12-11
            • 1970-01-01
            相关资源
            最近更新 更多