拡張メソッドの定義
this修飾子を使って静的メソッドを記述します。
「拡張メソッドの定義」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。
拡張メソッドとは
拡張メソッドを使うと、既存の型を変更したり派生型を作成したりせずに、新しいメソッドを追加できます。インスタンスメソッドのように呼び出しますが、実際には特殊なstaticメソッドです。
stringやintのように型のソースコードを所有していない場合でも、便利な新しい動作を追加できるため、拡張メソッドは特に役立ちます。
3つの要件
拡張メソッドを宣言するには、static class、static method、そしてthisキーワードを付けた最初のパラメーターが必要です。thisパラメーターによって、拡張する型を指定します。
using System;
public static class StringExtensions
{
public static int WordCount(this string text)
{
if (string.IsNullOrWhiteSpace(text)) return 0;
return text.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Length;
}
}
public class Program
{
public static void Main()
{
string sentence = "the quick brown fox";
Console.WriteLine(sentence.WordCount());
}
}インスタンスメソッドのように呼び出す
WordCountは static ですが、sentence.WordCount()のように呼び出せます。コンパイラは内部で、この呼び出しをStringExtensions.WordCount(sentence)に書き換えます。
using System;
using System.Linq;
public static class StringExtensions
{
public static string Repeat(this string text, int times)
{
return string.Concat(Enumerable.Repeat(text, times));
}
}
public class Program
{
public static void Main()
{
// These two lines do exactly the same thing
Console.WriteLine("ab".Repeat(3));
Console.WriteLine(StringExtensions.Repeat("ab", 3));
}
}this パラメーターがインスタンスを受け取る
ドットの左側にある値がthisパラメーターになります。その後ろにパラメーターを追加することもでき、呼び出し側では通常のように値を渡します。
using System;
public static class IntExtensions
{
public static bool IsBetween(this int value, int low, int high)
{
return value >= low && value <= high;
}
}
public class Program
{
public static void Main()
{
int age = 25;
Console.WriteLine(age.IsBetween(18, 65));
Console.WriteLine(10.IsBetween(1, 5));
}
}独自の型を拡張する
拡張メソッドはライブラリの型専用ではありません。独自のクラスも拡張できます。コアとなる型をシンプルに保ちながら、別の場所にヘルパー機能を追加できるため便利です。
using System;
public class Money
{
public decimal Amount { get; }
public Money(decimal amount) { Amount = amount; }
}
public static class MoneyExtensions
{
public static string ToUsd(this Money m) => "$" + m.Amount.ToString("0.00");
}
public class Program
{
public static void Main()
{
var price = new Money(19.5m);
Console.WriteLine(price.ToUsd());
}
}拡張メソッドから private メンバーにはアクセスできない
拡張メソッドは別のクラスにある static メソッドにすぎないため、型のpublicな領域(同じアセンブリ内であれば internal も含む)だけを利用できます。private フィールドにアクセスすることはできません。
using System;
public class Counter
{
private int _count;
public int Value => _count;
public void Increment() => _count++;
}
public static class CounterExtensions
{
// Can only use public members like Value and Increment
public static bool IsZero(this Counter c) => c.Value == 0;
}
public class Program
{
public static void Main()
{
var c = new Counter();
Console.WriteLine(c.IsZero());
c.Increment();
Console.WriteLine(c.IsZero());
}
}拡張メソッドのチェーン
各拡張メソッドは値を返すため、流れるようなパイプラインとして連結できます。上から下へ読み進められるこの書き方は、LINQで使われているスタイルです。
using System;
public static class TextExtensions
{
public static string Shout(this string s) => s.ToUpper();
public static string Bang(this string s) => s + "!";
}
public class Program
{
public static void Main()
{
string result = "hello".Shout().Bang();
Console.WriteLine(result);
}
}null と拡張メソッド
通常のインスタンス呼び出しとは異なり、拡張メソッドは呼び出し対象がnullでも実行できます。コードがその値を参照するまで、何も逆参照されないためです。これにより、null 安全なヘルパーを記述できます。
using System;
public static class StringExtensions
{
public static bool IsBlank(this string text)
{
// text may be null here, and that is fine
return string.IsNullOrWhiteSpace(text);
}
}
public class Program
{
public static void Main()
{
string nothing = null;
Console.WriteLine(nothing.IsBlank());
Console.WriteLine("x".IsBlank());
}
}インスタンスメソッドが拡張メソッドより優先される
一致するシグネチャを持つ実際のインスタンスメソッドが存在する場合、コンパイラは必ず拡張メソッドよりもそちらを優先します。拡張メソッドは、型がまだ対応していない機能を補うために使います。
using System;
public static class Ext
{
// This will be ignored because string already has ToString()
public static string ToString(this string s, int n) => s + n;
}
public class Program
{
public static void Main()
{
// Resolves to the built-in instance ToString(), not the extension
Console.WriteLine("value: " + "abc".ToString());
}
}実用的なヘルパーライブラリ
関連する拡張メソッドを1つの static class にまとめると、整理されたユーティリティライブラリになります。ここでは、プロジェクト全体で再利用できる小さな数値ヘルパークラスを紹介します。
using System;
public static class NumberExtensions
{
public static bool IsEven(this int n) => n % 2 == 0;
public static int Squared(this int n) => n * n;
public static double Percent(this int n) => n / 100.0;
}
public class Program
{
public static void Main()
{
Console.WriteLine(4.IsEven());
Console.WriteLine(5.Squared());
Console.WriteLine(50.Percent());
}
}自分で試す
学んだことを組み合わせてみましょう。1つの static class に複数の目的を絞った拡張メソッドを定義し、流れるように呼び出します。これは、日常的に使うヘルパーライブラリが作られる方法そのものです。
using System;
public static class StringExtensions
{
public static string Capitalize(this string s)
=> string.IsNullOrEmpty(s) ? s : char.ToUpper(s[0]) + s.Substring(1);
public static string Surround(this string s, char c) => c + s + c;
}
public class Program
{
public static void Main()
{
Console.WriteLine("hello".Capitalize().Surround('*'));
}
}確認問題
拡張メソッドの宣言についての理解度を確認しましょう。
要点の復習
拡張メソッドは、最初のパラメーターにthisを使う、staticクラス内のstaticメソッドです。インスタンス構文で呼び出しますが、コンパイル後は通常の static 呼び出しになります。
- 3つの要件は、static class、static method、最初のパラメーターの
thisです。 - アクセスできるのは public メンバーだけです。
- インスタンスメソッドが常に優先されます。
- 拡張メソッドは連結でき、
nullの呼び出し対象に対しても実行できます。
よくある質問
「拡張メソッドの定義」レッスンは無料ですか?
はい。「拡張メソッドの定義」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。
「拡張メソッドの定義」で何を学びますか?
this修飾子を使って静的メソッドを記述します。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C# Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「拡張メソッドの定義」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC# Academyレッスンでコードを書いて実行できますか?
はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 拡張メソッドの定義
- インターフェイスとジェネリックの拡張
- 拡張メソッドの解決
- 適切な拡張の設計