C#でファイルパスの正規化を行おうと思ったのですが、絶対パスならSystem.IO.Path.GetFullName()で可能ですが相対パスについては上手く動作するコードがなかったので、こちらで作ったコードを公開しようと思います。

一応テスト済みですが、もし不具合があったら教えて頂けると助かります。

// using System.Collections.Generic;
// using System.IO;
// using System.Linq;

public static string Regulate(string path)
{
    if (path == null)
        throw new ArgumentNullException(nameof(path));

    var root = Path.IsPathRooted(path);
    var net = path.StartsWith(@"\\");

    path = path.Trim(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
    var spath = new LinkedList<string>(path.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
        .Where(s => s != "." && s != string.Empty));
    var node = spath.First;

    while (node != null)
    {
        if (node.Value == "..")
        {
            var prev = node.Previous;
            if (prev != null && prev.Value != "..")
            {
                spath.Remove(prev);
                var rm = node;
                node = node.Next;
                spath.Remove(rm);
            }
            else
            {
                node = node.Next;
            }
        }
        else
        {
            node = node.Next;
        }
    }

    if (root && (spath.Count == 0 || spath.First.Value == ".."))
        throw new ArgumentException("ルートパスを超える..が含まれています。");

    path = Path.Combine(spath.ToArray());
    if (net)
        path = @"\\" + path;
    else if (root && !Path.IsPathRooted(path))
        path = Path.DirectorySeparatorChar + path;

    return path;
}