もこたんブログ@mocuLab(・ω・)

Programming & Designing

C#の拡張メソッドの作り方。拡張メソッドを定義する方法

Microsoft公式 拡張メソッド (C# プログラミング ガイド)
拡張メソッド (C# プログラミング ガイド) | Microsoft Docs

大抵のものは標準で揃っているけれども、そこにない処理を個別に追加できます。

拡張メソッドとは…

既存の型(クラスなど)にメソッドを追加できます。その追加されたメソッドのことです。

拡張メソッドを使うと、StringクラスやDatetimeクラスなど、変更できないクラスにもメソッドを追加できます。クラス自体には変更を加えないでメソッドの追加だけをできます。
→逆に言うと、変えられないクラスにメソッドを追加できる!

構文

拡張メソッドは、静的クラスの静的メソッドとして定義します。また、追加するメソッドの最初のパラメータには、thisキーワードで拡張するクラスを指定します。

public static 拡張メソッド名( this 拡張する型, パラメータリスト )
{
    // 処理
}
拡張メソッドを定義するクラスの条件

入れ子になってない
ジェネリックじゃない※ジェネリッククラスの例:Listとか
・静的クラス(static)
・public
クラス名はなんでもいいですが、わかりやすく「~Extend」「~Ex」「~Extensions」などを付けることが多そうです。  

拡張メソッドの条件

・静的メソッド(static)
・public
・引数の最初に「this 拡張する型名」で拡張したい型を指定

拡張メソッドを定義する例

例として、「00、01、02、03…」など、左が0埋めされている文字列を「0、1、2、3…」という形に変換するメソッドを、stringの拡張メソッドとして作るとします(標準ではなかったはず…あるっけ?)。左の0をトリムするので、メソッド名はTrimLeftZeroとしてみました。

コンソールアプリを新規作成して、Mainから呼んでみます。 f:id:mocotanus:20171006125317p:plain

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Util;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            var list = new List<string>()
            {
                "00",// "0"にする
                "01",// "1"にする
                "02",// "2"にする
            };

            foreach (var s in list)
            {
                string value = s.TrimLeftZero();
                Console.WriteLine(value);
            }

            var today = DateTime.Today;
            var lastDate = today.GetLastDateOfMonth();
            Console.WriteLine(today.ToString("yyyy.MM.dd") + " の月末は " + lastDate.ToString("yyyy.MM.dd"));

            Console.ReadLine();
        }
    }
}

同じプロジェクト内に、拡張メソッド用の別ファイルを作った場合。別ファイル(StringExtensions.cs)>StringExtensionsクラス>TrimLeftZeroメソッド
f:id:mocotanus:20171006125322p:plain

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication3
{
    public static class StringExtensions
    {
        #region TrimLeftZero:左にある連続した0を削除する
        /// <summary>
        /// 左にある連続した0を削除する
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string TrimLeftZero(this string value)
        {
            if (value == null) return "";
            if (value == "") return "";

            int i = 0;
            bool res = int.TryParse(value, out i);

            // 数字に変換できる場合は文字列にして返す
            if (res) return i.ToString();
            // 数字に変換できない場合はそのまま返す
            return value;
        }
        #endregion
    }
}

別プロジェクトにライブラリクラスとして作成した場合。プロジェクト名Util>ExtensionMethods.cs>DateTimeExtendクラス>GetLastDateOfMonthメソッド 「last day of month」は聞くけど、「last date of month」って言うのかはわかりません(´・ω・`)ある日付の月末の日付をDateTime型で取得するメソッドです。標準でありそうだけど。
f:id:mocotanus:20171006125326p:plain

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Util
{
    /// <summary>
    /// DateTimeの拡張メソッド
    /// </summary>
    public static class DateTimeExtend
    {
        #region GetLastDateOfMonth:日付の最終日の日付を取得する
        /// <summary>
        /// 日付の最終日の日付を取得する
        /// 例)「2017/10/6」から「2017/10/31」を取得する
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static DateTime GetLastDateOfMonth(this DateTime value)
        {
            DateTime tempDate = value.AddMonths(1);
            DateTime lastDate = new DateTime(tempDate.Year, tempDate.Month, 1);
            lastDate = lastDate.AddDays(-1);
            return lastDate;
        } 
        #endregion
    }
}