I'd like to point out some of the pitfalls of using a raw string as a representation of a path, too.
You've got to manually normalize strings before any comparison is done. Even a single directory delimer at the end of the string means that the paths won't compare correctly. This takes a good amount of extra code to do so, and you've got to remember to normalize *everywhere*, or you've got a bug waiting to happen. string s1 = `baz/../foo/bar/`; string s2 = `foo/bar/`; string s3 = `foo/bar`; assert(s1 == s2); // Fails assert(s2 == s3); // Fails assert(s1 == s3); // Fails assert(buildNormalizedPath(s1) == buildNormalizedPath(s2)); // Passes, with many more keystrokes. Comparing with Paths: Path p1 = `baz/../foo/bar/`; Path p2 = `foo/bar/`; Path p2 = `foo/bar`; assert(p1 == p2); // Passes. assert(p2 == p3); // Passes. assert(p1 == p3); // Passes. As you can see, Path is just generally easier to work with, because it encapsulates the concept a path. There's no having to normalize strings, because that's done for you. It just works. Building a path with strings isn't difficult, but the function calls are unweildy. string s1 = buildNormalizedPath(`foo`, `bar`); string s2 = buildNormalizedPath(s1, `baz`); assert(s2 == `foo/bar/baz`); // Will fail on some platforms. Building a Path, IMO, just looks cleaner, and it's obvious what you're doing. Path p1 = Path(`foo`, `bar`); Path p2 = p1.join(`baz`); assert(p2 == `foo/bar/baz`); // Passes on all platforms. As a sidenote, I'd like to point out that using Path has *no more overhead* than passing around and manipulating a raw string. As far as I can tell, all use cases for Path takes less code, and more easily convays what you're doing. D's support for object oriented design is great; why not make use of it?
