Просматривая ответы здесь, все они **, похоже, используют массив символов недопустимых символов имени файла.
Конечно, это может быть микрооптимизацией, но для тех, кто хочет проверить большое количество значений на предмет допустимости имен файлов, стоит отметить, что создание хэш-набора недопустимых символов приведет к заметному повышению производительности.
В прошлом я был очень удивлен (шокирован) тем, насколько быстро хешсет (или словарь) превосходит итерации по списку. Со строками это смехотворно мало (около 5-7 пунктов по памяти). С большинством других простых данных (ссылки на объекты, числа и т. Д.) Магический кроссовер, кажется, составляет около 20 предметов.
В списке «Path» .InvalidFileNameChars содержится 40 недопустимых символов. Сделал поиск сегодня, и здесь есть довольно хороший тест на StackOverflow, который показывает, что хэш-сет займет чуть более половины времени массива / списка для 40 элементов: https://stackoverflow.com/a/10762995/949129
Вот вспомогательный класс, который я использую для очистки путей. Теперь я забываю, почему у меня была такая необычная возможность замены, но это было милым бонусом.
Дополнительный бонусный метод "IsValidLocalPath" тоже :)
(** те, которые не используют регулярные выражения)
public static class PathExtensions
{
private static HashSet<char> _invalidFilenameChars;
private static HashSet<char> InvalidFilenameChars
{
get { return _invalidFilenameChars ?? (_invalidFilenameChars = new HashSet<char>(Path.GetInvalidFileNameChars())); }
}
/// <summary>Replaces characters in <c>text</c> that are not allowed in file names with the
/// specified replacement character.</summary>
/// <param name="text">Text to make into a valid filename. The same string is returned if
/// it is valid already.</param>
/// <param name="replacement">Replacement character, or NULL to remove bad characters.</param>
/// <param name="fancyReplacements">TRUE to replace quotes and slashes with the non-ASCII characters ” and ⁄.</param>
/// <returns>A string that can be used as a filename. If the output string would otherwise be empty, "_" is returned.</returns>
public static string ToValidFilename(this string text, char? replacement = '_', bool fancyReplacements = false)
{
StringBuilder sb = new StringBuilder(text.Length);
HashSet<char> invalids = InvalidFilenameChars;
bool changed = false;
for (int i = 0; i < text.Length; i++)
{
char c = text[i];
if (invalids.Contains(c))
{
changed = true;
char repl = replacement ?? '\0';
if (fancyReplacements)
{
if (c == '"') repl = '”'; // U+201D right double quotation mark
else if (c == '\'') repl = '’'; // U+2019 right single quotation mark
else if (c == '/') repl = '⁄'; // U+2044 fraction slash
}
if (repl != '\0')
sb.Append(repl);
}
else
sb.Append(c);
}
if (sb.Length == 0)
return "_";
return changed ? sb.ToString() : text;
}
/// <summary>
/// Returns TRUE if the specified path is a valid, local filesystem path.
/// </summary>
/// <param name="pathString"></param>
/// <returns></returns>
public static bool IsValidLocalPath(this string pathString)
{
// From solution at https://stackoverflow.com/a/11636052/949129
Uri pathUri;
Boolean isValidUri = Uri.TryCreate(pathString, UriKind.Absolute, out pathUri);
return isValidUri && pathUri != null && pathUri.IsLoopback;
}
}