#●拡張メソッド
既存クラスに、継承を使わずにメソッドだけ追加するための仕組み
#●拡張メソッド定義構文
拡張メソッドであることの条件は2つ
・staticクラスのstaticメソッドであること
・第1引数として、thisキーワードをつけて拡張するクラスを指定すること
public static 戻り値の型 拡張メソッド(this 拡張するクラス 引数名, その他の引数)
{
メソッド本体
}
#●ソース
Sringクラスを拡張して、新たなRepeatメソッドを定義する。
指定回数だけ繰り返した文字列を取得
// Stringクラスを拡張したstaticクラス
// クラス名は、(対象のクラス+Extensions)とするといい
static class StringExtensions
{
// thisキーワードでStringクラスを拡張することを指定
// 第2引数意向で、拡張メソッド本来の引数を指定する(この場合はcount)
public static string Repeat(this string str, int count)
{
var builder = new StringBuilder();
for (int i = 0; i <= count; i++)
{
builder.Append(str);
}
return builder.ToString();
}
}
DateTimeクラスを拡張して、EndOfMonthメソッドを定義する。
指定した日付の月の最終日を取得する
// DateTimeクラスを拡張したstaticクラス
static class DateTimeExtensions
{
// thisキーワードでDateTimeクラスを拡張することを指定
public static DateTime EndOfMonth(this DateTime date)
{
return new DateTime(date.Year, date.Month, 1).AddMonths(1).AddDays(-1);
}
}
static void Main(string[] args)
{
var str = "Wow!";
Console.WriteLine(str.Repeat(5));
var date = DateTime.Now;
Console.WriteLine(date.EndOfMonth());
}
#列挙型、インターフェースでの拡張メソッド
拡張メソッドは列挙型(Enum)やインターフェースにも使用することができる
##列挙型
// 調味料を列挙
enum Seasoning
{
Salt,
Soy_Sauce,
Sugar
}
// Seasoningの拡張メソッド
static class SeasoningExtensions
{
public static string GetSeasoningString(this Seasoning kind)
{
switch (kind)
{
case Seasoning.Salt:
return "塩";
case Seasoning.Soy_Sauce:
return "醤油";
case Seasoning.Sugar:
return "砂糖";
default:
return "";
}
}
}
static void Main(string[] args)
{
// 全ての列挙子(値)を取得して表示
foreach (Seasoning kind in Enum.GetValues(typeof(Seasoning)))
{
Console.WriteLine(kind.GetSeasoningString());
}
}
##インターフェース
実装を定義できないインターフェースでも拡張メソッドが利用可能。
static class Extensions
{
// 条件で絞る機能の追加
public static IEnumerable<int> Where(this IEnumerable<int> array, Func<int, bool> pred)
{
foreach (var x in array)
if (pred(x))
yield return x;
}
// 値を加工する機能を追加
public static IEnumerable<int> Select(this IEnumerable<int> array, Func<int, int> filter)
{
foreach (var x in array)
yield return filter(x);
}
}
static void Main(string[] args)
{
var input = new[] { 8, 9, 10, 11, 12, 13 };
var output = input
.Where(x => x > 10)
.Select(x => x * x);
}
#まとめ
コードが読みやすくなったり、もう少し機能が欲しかったものに追加することができる反面、定義箇所が分かりづらくなるなどのデメリットもあるので、濫用は避けた方がいい。
#・参照
[拡張メソッド ++C++; // 未確認飛行 C ]
(https://ufcpp.net/study/csharp/sp3_extension.html#interface)