1: using System;
2: using System.Text;
3: using ioPath = System.IO.Path;
4:
5: namespace Utils
6: { 7: public sealed class Path
8: { 9: private Path() { } 10:
11: public static string Combine(params string[] paths) { 12: if (paths.Length == 2) return ioPath.Combine( paths[0], paths[1] );
13:
14: StringBuilder combined = new StringBuilder(50);
15: foreach(string path in paths) { 16: if (path == null) throw new ArgumentNullException("path array item"); 17: Path.CheckInvalidPathChars(path);
18: if ( path.Length > 0 ) { 19: if (ioPath.IsPathRooted(path)) { 20: combined = new StringBuilder(50).Append(path);
21: }
22: else { 23: char ch1;
24: if (combined.Length > 0) { 25: ch1 = combined[combined.Length - 1];
26: }
27: else { 28: ch1 = path[path.Length - 1];
29: }
30: if (((ch1 != ioPath.DirectorySeparatorChar) &&
31: (ch1 != ioPath.AltDirectorySeparatorChar)) &&
32: (ch1 != ioPath.VolumeSeparatorChar)) { 33: combined.Append(ioPath.DirectorySeparatorChar + path);
34: }
35: else { 36: combined.Append(path);
37: }
38:
39: }
40: }
41: }
42: return combined.ToString();
43: }
44:
45: internal static void CheckInvalidPathChars(string path) { 46: if (-1 != path.IndexOfAny(System.IO.Path.InvalidPathChars)) { 47: throw new ArgumentException("InvalidPathChars"); 48: }
49: }
50:
51: }
52: }
I tried to call the Path class's public members as much as possible to improve upgradability to the next version of the .NET Framework. The CheckInvalidPathChars internal method is the same as the System.IO.Path class's method of the same name. I used Reflector to check it out.
From my performance testing, the built-in Path.Combine performs about 60 nanoseconds faster on two arguments. For three arguments, the code above performs marginally better than calling Path.Combine twice, once with the first two arguments and once with the result and a third argument. At four arguments or more it really outperforms the built-in Path.Combine. Maybe it's not all that useful, but it was fun to do.