Если у меня много имен каталогов в виде буквальных строк или содержащихся в переменных, как проще всего их объединить для создания полного пути?
я знаю
Path.Combinebut this only takes 2 string parameters, i need a solution that can take any number number of directory parameters.
например:
string folder1 = "foo";
string folder2 = "bar";
CreateAPath("C:", folder1, folder2, folder1, folder1, folder2, "MyFile.txt")
Есть идеи? Поддерживает ли C# неограниченное количество аргументов в методах?





Does C# support unlimited args in methods?
Да, взгляните на ключевое слово params. Упростит написание функции, которая просто вызывает Path.Combine соответствующее количество раз, как это (непроверено):
string CombinePaths(params string[] parts) {
string result = String.Empty;
foreach (string s in parts) {
result = Path.Combine(result, s);
}
return result;
}
Согласно bytes.com/forum/thread453111.html, между ними нет точно никакой разницы, и компилятор фактически будет создавать одинаковый IL для обоих. Но для удобочитаемости изменю.
Попробуй это:
public static string CreateDirectoryName(string fileName, params string[] folders)
{
if (folders == null || folders.Length <= 0)
{
return fileName;
}
string directory = string.Empty;
foreach(string folder in folders)
{
directory = System.IO.Path.Combine(directory, folder);
}
directory = System.IO.Path.Combine(directory, fileName);
return directory;
}
Параметры позволяют добавлять бесконечное количество строк.
Path.Combine гарантирует, что введенные строки не начинаются или не заканчиваются косой чертой, и проверяет наличие недопустимых символов.
Пожалуйста, позвольте методам System.IO.Path обрабатывать такие вещи, как обрезка или добавление обратной косой черты.
Хорошо, я говорю по-другому. Зачем заново изобретать колесо? Эта жестко запрограммированная вещь действительно кажется вам более понятной? Что, если вы работаете в системе * NIX с косой чертой в качестве разделителя пути? Что, если один из путей абсолютен? Path.Combine также справляется с этим.
О, обычное дело, теперь вы действительно заново изобретаете Path.Combine. Он есть, так что используйте его: weblogs.asp.net/rchartier/archive/2006/01/26/436584.aspx
Проголосовал против, потому что это все еще неверно в отношении Path.Combine, все равно не удастся с абсолютными путями, обработка подстановочных знаков неясна и является потенциально эффективным, но сложным решением.
Мне жаль, что мне пришлось настоять на этом, но я не хотел, чтобы это было неправильно. Мы должны это сделать, верно? Однако я не собирался ударить вас лично.
LINQ снова приходит на помощь. Функцию расширения Совокупный можно использовать для выполнения того, что вы хотите. Рассмотрим этот пример:
string[] ary = new string[] { "c:\", "Windows", "System" };
string path = ary.Aggregate((aggregation, val) => Path.Combine(aggregation, val));
Console.WriteLine(path); //outputs c:\Windows\System
Хороший. Способ узнать доступные операции последовательности!
Microsoft проделала действительно хорошую работу с LINQ. Каждый раз, когда мне нужно сделать что-нибудь необычное с коллекцией, я сразу же заглядываю в библиотеки LINQ.
Я предпочитаю использовать DirectoryInfo вместо статических методов в Directory, потому что считаю, что это лучший объектно-ориентированный дизайн. Вот решение с методами расширения DirectoryInfo +, которое, на мой взгляд, очень удобно использовать:
public static DirectoryInfo Subdirectory(this DirectoryInfo self, params string[] subdirectoryName)
{
Array.ForEach(
subdirectoryName,
sn => self = new DirectoryInfo(Path.Combine(self.FullName, sn))
);
return self;
}
Мне не нравится тот факт, что я модифицирую self, но для этого короткого метода, я думаю, он чище, чем создание новой переменной.
Однако сайт звонка компенсирует это:
DirectoryInfo di = new DirectoryInfo("C:\")
.Subdirectory("Windows")
.Subdirectory("System32");
DirectoryInfo di2 = new DirectoryInfo("C:\")
.Subdirectory("Windows", "System32");
Добавление способа получения FileInfo оставлено как упражнение (для другого вопроса SO!).
Может ли кто-нибудь объяснить, почему мой ответ отклонен? Есть проблема, которую я не заметил?
@OregonGhost: +1, но переключите "" на String.Empty.