2

We ran into the same kind of behaviour exhibited by this post:

Why does Path.Combine produce this result with a relative path?

Where:

var basePath = @"\\server\BaseFolder";
var relativePath = @"\My\Relative\Folder";

var combinedPath = Path.Combine(basePath, relativePath);

produces an output of \My\Relative\Folder instead of the expected \\server\BaseFolder\My\Relative\Folder.

After reading this and other posts, as well as the MSDN doc:

If the one of the subsequent paths is an absolute path, then the combine operation resets starting with that absolute path, discarding all previous combined paths.

I understand this behaviour exactly, as well as what it's doing and how to fix it.

What I don't understand is why!

In what scenarios would this be the required behavior? Why would you ever want to pass in a set of arguments here, and have it completely ignore whatever first few you pass in and just take the last few instead?

Surely this would be better treated by Microsoft as an exception rather than just ignoring the parameters - if an absolute path is tried to be merged with a path which was already absolute surely that's an invalid argument...

Probably going to write my own method to do what I want, just wanted to get everyone's opinion on why it could have been purposely designed like this.

Community
  • 1
  • 1
GoldieLocks
  • 845
  • 7
  • 22
  • 1
    It's not "ignoring" the arguments at all. It's combining them. When you combine paths and one of them is a root path, the overall path logically starts over at the root. Just like when changing directories on the command line. You can issue a bunch of `cd` commands, if one of those commands references a root path then you'll start over from that root path. – David Oct 22 '14 at 12:15
  • I wouldn't say it's combining them in the way one would expect looking at the face of a Path.Combine method without examining the history of DOS. A method which takes input strings which make up a single path, and output the full path generated from these input strings. Not take a number of potentially different roots and output the last root you find! – GoldieLocks Oct 22 '14 at 12:19
  • 1
    @GoldieLocks But it *is* combining them. It does return the single (valid) path that is a combination of all the input paths. This has nothing to do with DOS - it has everything to do with file systems and UNC. – Luaan Oct 22 '14 at 12:21
  • 1
    Maybe it's not behaving the way *you* expect, but that's a very subjective and opinion-driven position. Don't confuse `Path.Combine()` with `string.Join()`, they do very different things. Each individual path isn't just a string, it represents pointer to a file system location. When they're combined, those pointers are evaluated in the order they're provided. – David Oct 22 '14 at 12:21
  • I wouldn't say I am confusing those methods as I understand the difference, and what I would imagine the difference in functionality to be - it's just that the way it's implemented isn't what I would imagine the logical implementation to be. You're 100% right, it's my opinion - I only asked the question to get other's opinions and see if I could make any sense over the design of the method. – GoldieLocks Oct 22 '14 at 12:24

1 Answers1

5

Simple. Your relativePath is not actually a relative path.

The correct path must not start with a \ - that roots it. If you use My\Relative\Folder, it will work as you expect it to.

In fact, you'll see this kind of behaviour in many places, including the windows command processor. If I am in C:\Windows, what will dir \ print out?

Luaan
  • 62,244
  • 7
  • 97
  • 116
  • I understand that completely, what I don't understand is why passing in a rooted path half way through an already rooted path doesn't throw an exception, rather than just ignoring whatever was originally at the start! – GoldieLocks Oct 22 '14 at 12:13
  • @GoldieLocks Because it's the standard way to combine paths? Why should they break the estabilished protocol? :) – Luaan Oct 22 '14 at 12:14
  • Also you could add a dot before the slash (.\\) to make it relative. – juharr Oct 22 '14 at 12:18
  • My comment above - without knowledge of DOS (which should be an independent technology from .Net coding libraries, and only cross over if you explicitly get it to) - I wouldn't say it's combining them in the way one would expect looking at the face of a Path.Combine method. A method which takes input strings which make up a single path, and output the full path generated from these input strings. Not take a number of potentially different roots and output the last root you find! – GoldieLocks Oct 22 '14 at 12:21
  • 1
    @GoldieLocks: `"which should be an independent technology from .Net coding libraries"` ... This particular library is operating on *file system* concepts. Why should the *file system* not be a consideration when doing that? – David Oct 22 '14 at 12:23
  • @GoldieLocks You're always working with some abstractions. If UNC paths aren't universal enough for you, what is? Perhaps you don't actually want to work with string paths at all? When you're working with string paths, you're working with UNC/DOS paths. You don't have to do that. And most importantly, don't forget that while .NET itself is multi-platform, the users aren't. `Path.Combine` can behave differently on Linux, but it should behave the way the user expects it to there. – Luaan Oct 22 '14 at 12:23
  • @David yeah maybe my comment wasn't thought out as well as it could have been, but I don't see Windows Explorer working in this way. If you have an explorer window open with "C:\Windows" in the address bar, adding "\Fonts" (essentially combining "C:\Windows" and "\Fonts") doesn't try and redirect me off to "\\fonts\"? – GoldieLocks Oct 22 '14 at 12:27
  • @GoldieLocks Yeah, but that's where you're confused. There's a difference between doing `Combine("C:\Windows\", "\Fonts")` and `Combine("C:\Windows\", "Fonts\")`. Try putting `C:\Windows\\Fonts` in the Explorer address bar. The proper path to a directory *always* ends with a backslash. If you want the same behaviour in your application, just use `"C:\Windows\" + "\Fonts"` :) – Luaan Oct 22 '14 at 12:29
  • @GoldieLocks - You seem to be thinking that that `Path.Combine` should be doing a string concatenation of the input paths, but that's not what's happening. – Chris Dunaway Oct 22 '14 at 15:53