13

System.IO.Directory.GetParentメソッドの非常に奇妙な動作に直面しました。

string path1 = @"C:\foo\bar";
DirectoryInfo parent1 = Directory.GetParent(path1);
Console.WriteLine (parent1.FullName); // Prints C:\foo, as expected

// Notice the extra backslash. It should still refer to the same location, right ?
string path2 = @"C:\foo\bar\";
DirectoryInfo parent2 = Directory.GetParent(path2);
Console.WriteLine (parent2.FullName); // Prints C:\foo\bar !!!

バグだと思いますが、このメソッドは 1.0 から存在していたので、今頃には検出されていたと思います。一方で、設計通りだとしたら、そのような設計の合理的な説明は思いつきません...

どう思いますか ?バグですか?そうでない場合、この動作をどのように説明しますか?

4

3 に答える 3

11

いくつかのグーグルはいくつかの考えを明らかにします:

DirectoryInfo di = new DirectoryInfo(@"C:\parent\child");
Console.WriteLine(di.Parent.FullName);

DirectoryInfo di = new DirectoryInfo(@"C:\parent\child\");
Console.WriteLine(di.Parent.FullName);

どちらも「C:\parent」を返します

ファイル拡張子のないファイルではなく、ディレクトリであるとは想定Directory.GetParent(...)できないと思います。オブジェクトをそのように構築しているためです。C:\parent\childDirectoryInfo


個人的に思うのは、バックスラッシュがあると文字列はディレクトリ内の「空ファイル」(つまり、名前も拡張子もないファイル)へのパスとして扱われるということです。どうやら、それらは存在する可能性があります (リンクがあるはずですが、何らかの理由で何も見つかりません)。

FileInfoからオブジェクトを作成してみてくださいpath2。適切に構築さString.Emptyれ、名前と拡張子が であり、存在せず、がであることがわかりC:\foo\barますDirectoryName。それを考えると、状況は理にかなっています。この「null ファイル」の親オブジェクトは確かにC:\foo\barです。

于 2010-10-18T23:24:50.763 に答える
3

私はGSergに同意します。火力を追加するためだけに、Reflector で取得した次のコード スニペットを追加します。

Directory.GetParent 関数は、基本的に Path.GetDirectoryName 関数を呼び出すだけです。

[SecuritySafeCritical]
public static DirectoryInfo GetParent(string path)
{
    if (path == null)
    {
        throw new ArgumentNullException("path");
    }
    if (path.Length == 0)
    {
        throw new ArgumentException(Environment.GetResourceString("Argument_PathEmpty"), "path");
    }
    string directoryName = Path.GetDirectoryName(Path.GetFullPathInternal(path));
    if (directoryName == null)
    {
        return null;
    }
    return new DirectoryInfo(directoryName);
}

DirectoryInfo の Parent プロパティは、基本的に末尾のスラッシュを取り除き、Path.GetDirectoryName を呼び出します。

public DirectoryInfo Parent
{
    [SecuritySafeCritical]
    get
    {
        string fullPath = base.FullPath;
        if ((fullPath.Length > 3) && fullPath.EndsWith(Path.DirectorySeparatorChar))
        {
            fullPath = base.FullPath.Substring(0, base.FullPath.Length - 1);
        }
        string directoryName = Path.GetDirectoryName(fullPath);
        if (directoryName == null)
        {
            return null;
        }
        DirectoryInfo info = new DirectoryInfo(directoryName, false);
        new FileIOPermission(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, info.demandDir, false, false).Demand();
        return info;
    }
}
于 2010-10-18T23:52:13.373 に答える
1

これはかなり興味深いです。最初にこれを読んだとき、これはバグであると確信していましたが、もう少し考えてみると、パスはディレクトリではなく、絶対パスまたは相対パスであるべきだという結論に達しました。ファイル。そう

c:\somenonexistingpath\to\a\directory\

...\directory 内の名前のないファイルへのパスとして解釈されます。ちょっとばかげていますが、Microsoft のプログラマーがファイルへのフル パスを期待していたと仮定すると、このケースを扱わないのが理にかなっています。

編集:

ご了承ください

c:\dir\makefile -> c:\dir

c:\dir\build.msbuild -> c:\dir

期待どおりに親を与えます。

于 2010-10-18T23:44:20.017 に答える