C#:文字数を気にせずに文字列を切り出す【Left、Right、Mid】【拡張メソッド使用】

C#で文字列を切り出すにはSubstring関数を使用します。この関数は文字数を気にしてコーディングしないと例外が発生してしまいます。

例えば、下記のコードでは、操作対象の文字列よりも長い文字数を切り出そうとしているので例外(System.ArgumentOutOfRangeException)が発生してエラーになります。

string str = "test";
str.Substring(0, 10);

Microsoft.VisualBasic名前空間のStringsクラスにあるLeft、Right、Mid関数などを使用すれば文字数を気にしなくても良くて楽なのですが、C#でVBの関数を使用するのは何となく抵抗があるので、拡張メソッドを使用して自作してみました。

拡張メソッドを使用してLeft、Right、Mid関数を実装する

拡張メソッドとは

既存の型やクラスに対して継承や変更を行うことなく、メソッドを追加できる仕組みのことです。

ソースコード

VBのLeft、Right、Mid関数をC#で拡張メソッドを使用して実装しました。(ただし、このコードのMid関数はVBと異なり、文字の取得開始位置を0から始まる番号で指定するようにしています。

拡張メソッドは静的(static)クラスの中に定義します。メソッドの第一引数には、メソッドによって操作される型を指定し、this修飾子を頭に付けます。

今回はstringクラスに対して拡張メソッドを定義します。

public static class MyExtensions
{
    /// <summary>
    /// 文字列の先頭から指定した文字数分の文字列を返します。
    /// </summary>
    /// <param name="str"></param>
    /// <param name="length">取得する文字数</param>
    /// <returns></returns>
    public static string Left(this string str, int length)
    {
        if (length < 0)
        {
            throw new ArgumentException("Length の値を 0 より小さくすることはできません。");
        }
        if (str == null)
        {
            return string.Empty;
        }
        if (length > str.Length)
        {
            return str;
        }
        return str.Substring(0, length);
    }

    /// <summary>
    /// 文字列の終端から指定した文字数分の文字列を返します。
    /// </summary>
    /// <param name="str"></param>
    /// <param name="length">取得する文字数</param>
    /// <returns></returns>
    public static string Right(this string str, int length)
    {
        if (length < 0)
        {
            throw new ArgumentException("Length の値を 0 より小さくすることはできません。");
        }
        if (str == null)
        {
            return string.Empty;
        }
        if (length > str.Length)
        {
            return str;
        }
        return str.Substring(str.Length - length, length);
    }

    /// <summary>
    /// 文字列の指定した位置から、指定した文字数分の文字列を返します。
    /// </summary>
    /// <param name="str"></param>
    /// <param name="start">0から始まる開始文字位置</param>
    /// <param name="length">取得する文字数</param>
    /// <returns></returns>
    public static string Mid(this string str, int start, int length)
    {
        if (length < 0)
        {
            throw new ArgumentException("Length の値を 0 より小さくすることはできません。");
        }
        if (str == null || start >= str.Length)
        {
            return string.Empty;
        }
        if (str.Length < start + length) 
        {
            return str.Substring(start);
        }
        return str.Substring(start, length);           
    }

    /// <summary>
    /// 文字列の指定した位置以降の文字列を返します。
    /// </summary>
    /// <param name="str"></param>
    /// <param name="start">0から始まる開始文字位置</param>
    /// <returns></returns>
    public static string Mid(this string str, int start)
    {
        if (str == null)
        {
            return string.Empty;
        }
        return Mid(str, start, str.Length);           
    }
}

テストコード

実装した拡張メソッドの動作確認を行うためのコードです。

private void button1_Click(object sender, EventArgs e)
{
    string str = "1234567890";
    Console.WriteLine("操作対象の文字列: " + str);

    Console.WriteLine("左から4文字を切り出し -> " + str.Left(4));
    Console.WriteLine("左から20文字を切り出し -> " + str.Left(20));

    Console.WriteLine("右から4文字を切り出し -> " + str.Right(4));
    Console.WriteLine("右から20文字を切り出し -> " + str.Right(20));

    Console.WriteLine("5文字目以降を切り出し -> " + str.Mid(4));
    Console.WriteLine("5文字目から3文字を切り出し -> " + str.Mid(4, 3));
    Console.WriteLine("5文字目から20文字を切り出し -> " + str.Mid(4, 20));
    Console.WriteLine("15文字目から5文字を切り出し -> " + str.Mid(14, 5));
}

拡張メソッドは、拡張された型のインスタンスメソッドのように呼び出すことができます。

実行結果

テストコードの実行結果です。

操作対象の文字列: 1234567890
左から4文字を切り出し -> 1234
左から20文字を切り出し -> 1234567890
右から4文字を切り出し -> 7890
右から20文字を切り出し -> 1234567890
5文字目以降を切り出し -> 567890
5文字目から3文字を切り出し -> 567
5文字目から20文字を切り出し -> 567890
15文字目から5文字を切り出し -> 

操作対象の文字列よりも長い文字数を切り出そうとしたり、Mid関数で文字列の長さを超えて開始位置を指定しても例外は発生しません。

まとめ

拡張メソッドを使用してstringクラスにLeft、Right、Mid関数を追加してみました。これによって、文字列の切り出しに文字数を気にしなくてよくなりました。

Left、Rightに関してはSubstringよりも文字列に対して何を行いたいのかが明確で、コードも読みやすくなると思います。

タイトルとURLをコピーしました