Architect's Log

I'm a Cloud Architect. I'm highly motivated to reduce toils with driving DevOps.

ファイル名の変更を拡張メソッドで実装する

ファイル名の変更が必要なケースは珍しくありませんが、System.IO.FileにもSystem.IO.FileInfoにも名前を変更するメソッドはありません。
そこで、ファイル名の変更を拡張メソッドでFileInfoに実装してみました。内部ではFileInfo.MoveToメソッドを使用しています。

IOExtensions.cs

using System;
using System.IO;

namespace Extensions {
    public static class IOExtensions {
        /// <summary>
        /// ファイルの名前を変更します。
        /// </summary>
        /// <param name="self">変更するファイルを示すFileInfo。</param>
        /// <param name="newName">変更後の名前。</param>
        public static void Rename(this FileInfo self, string newName) {
            if (Directory.Exists(self.FullName)) {
                throw new FileNotFoundException("指定されたパスはディレクトリです。path:" + self.FullName);
            }
            if (self.Exists == false) {
                throw new FileNotFoundException("指定されたファイルが見つかりません。path:" + self.FullName);
            }

            self.MoveTo(Path.Combine(self.DirectoryName, newName));
        }
    }
}

IOExtensionsTest.cs

using System;
using System.IO;
using Extensions;
using NUnit.Framework;

namespace ExtensionsTest {
    [TestFixture]    
    public class IOExtensionsTest {
        [Test]
        public void ファイルが存在しないときはエラー() {
            Exception ex = Assert.Throws<FileNotFoundException>(() => new FileInfo(@"c:\missing").Rename("new.txt"));
            StringAssert.StartsWith("指定されたファイルが見つかりません。", ex.Message);
        }

        [Test]
        public void ディレクトリの場合はエラー() {
            Exception ex = Assert.Throws<FileNotFoundException>(() => new FileInfo(@"C:\temporary").Rename("new.txt"));
            StringAssert.StartsWith("指定されたパスはディレクトリです。", ex.Message);
        }

        [Test]
        public void リネーム() {
            new FileInfo(@"C:\temporary\old.txt").Rename("new.txt");
            Assert.IsTrue(File.Exists(@"C:\temporary\new.txt"));
        }
    }
}