Earn More by Sharing What You Love
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!

Tim Corey
28分27秒
C# プログラミングでは、メソッドは再利用可能なコードをカプセル化し、特定のタスクを実行する重要なビルディングブロックです。 これらの開発ツールは、パラメータを受け取り、値を返し、さまざまな入力を処理するためにオーバーロードすることができます。 より高度な概念である拡張メソッドは、開発者が制御していない型も含め、既存の型に機能を追加することを可能にします。
ティム・コリーのビデオ"C#で拡張メソッドを作成する方法"は優れたリソースです。 このガイドでは、Timがカバーするいくつかのトピックを探ります:
1.メソッドの定義と呼び出し 2.メソッドのパラメータと引数 3.メソッドの戻り値 4.メソッドのオーバーロード 5.Extensionメソッドの実装
C#では、メソッドはクラス内で定義されます。 メソッド定義の一般的な構文には、アクセス修飾子、戻り値型、メソッド名、パラメータが含まれます。
public class SampleClass
{
public void SampleMethod()
{
// Method implementation
}
}Public Class SampleClass
Public Sub SampleMethod()
' Method implementation
End Sub
End ClassTim Coreyの4:05の例では、彼は静的クラス内でメソッドを定義し、拡張メソッドを作成している。 定義されたメソッドはPrintToConsoleです。 定義には一般的な構文がすべて含まれ、実用的な例を用いてメソッドの定義方法を明確に説明します:
public static class Extensions
{
public static void PrintToConsole(this string message)
{
Console.WriteLine(message);
}
}Public Module Extensions
<System.Runtime.CompilerServices.Extension> _
Public Sub PrintToConsole(ByVal message As String)
Console.WriteLine(message)
End Sub
End Moduleメソッドコール"は、コード内の別の場所に定義された特定のメソッドを実行し、事前に定義されたアクションを実行するようプログラムに指示します。 メソッドは、クラスのインスタンスを使用して呼び出されるか、静的メソッドの場合は直接呼び出されます。 拡張メソッドについては、拡張する型の一部であるかのように表示されます。 6:18のビデオでは、Timが、定義済みのメソッドと同じように、プリミティブなデータ型で拡張メソッドを呼び出す方法を示しています。
string demo = "This is a demo";
demo.PrintToConsole(); // Extension method callDim demo As String = "This is a demo"
demo.PrintToConsole() ' Extension method callパラメータはメソッド定義で指定され、メソッドに渡される値のプレースホルダとして機能します。 ここで、messageがパラメータであることがわかります。
public void DisplayMessage(string message)
{
Console.WriteLine(message);
}Public Sub DisplayMessage(message As String)
Console.WriteLine(message)
End Sub再び、4:05にティム・コーリーが挙げた拡張メソッドの例では、messageがパラメータです。
public static void PrintToConsole(this string message)
{
Console.WriteLine(message);
}<Extension()>
Public Sub PrintToConsole(ByVal message As String)
Console.WriteLine(message)
End Sub引数は、メソッドが呼び出されたときに渡される実際の値です。
DisplayMessage("Hello, World!"); // "Hello, World!" is the argumentDisplayMessage("Hello, World!") ' "Hello, World!" is the argumentティム・コーリーが6:20にドット構文を使用して文字列タイプでメソッドを呼び出す際、実際には文字列値がPrintToConsoleメソッドに値として渡されます。
string demo = "This is a demo";
demo.PrintToConsole(); // "This is a demo" is the argumentDim demo As String = "This is a demo"
demo.PrintToConsole() ' "This is a demo" is the argumentメソッドは return 文を使って値を返すことができます。 戻り値の型は、メソッドのシグネチャで指定します。
public int Add(int a, int b)
{
return a + b;
}Public Function Add(a As Integer, b As Integer) As Integer
Return a + b
End FunctionTim Coreyのビデオに登場する拡張メソッドは値を返しませんが(void戻り値型)、戻り値を持つ拡張メソッドを作成することができます。 Tim の例の戻り値の型は void で、これはメソッドが値を返さないことを意味します。 次の例は、値を返す方法を示しています:
public static int WordCount(this string str)
{
return str.Split(' ').Length;
}<Extension()>
Public Function WordCount(ByVal str As String) As Integer
Return str.Split(" "c).Length
End Functionメソッドのオーバーロードは、複数のメソッドが同じ名前で異なるパラメータを持つことを可能にします。 これは、柔軟で直感的なAPIの作成に役立ちます。
public void Display(string message)
{
Console.WriteLine(message);
}
public void Display(int number)
{
Console.WriteLine(number);
}Public Sub Display(message As String)
Console.WriteLine(message)
End Sub
Public Sub Display(number As Integer)
Console.WriteLine(number)
End Subティム・コリーは、11:24で異なるロギングシナリオのために複数のメソッドを作成することについて簡単に触れていますが、これは広い意味でのメソッドのオーバーロードの例として見ることができます。 logメソッドは、1つのパラメータを持つものと2つのパラメータを持つものの2つ存在します。 11:39の2番目のログメソッドは、ログメソッドのオーバーロード版で、同じ名前で複数の機能を与えている。
拡張メソッドを使用すると、既存の型を変更したり再コンパイルしたりすることなく、既存の型に新しいメソッドを追加できます。 拡張メソッドはインスタンスメソッドのように呼ばれますが、静的メソッドとして定義されます。
前のセクション"メソッドの定義と呼び出し"では、ティム・コリーが別の静的クラスで拡張メソッドを作成し、その中で静的メソッドを定義して拡張メソッドとして使用する方法を紹介しました。 以下は、ティム・コーリーが強調するポイントです:
1.必ず別のpublic staticクラスを定義するか、ティムが言うように、"staticとマークしないと動作しません"。
2.より多くの拡張メソッドを作成したら、それらをタイプ別にグループ化する(3:43)
3. 最初のパラメータをthisキーワードで接頭辞として定義し、拡張する型を指定する静的メソッドを定義します (4:58)
public static class Extensions
{
public static void PrintToConsole(this string message)
{
Console.WriteLine(message);
}
}Public Module Extensions
<System.Runtime.CompilerServices.Extension> _
Public Sub PrintToConsole(ByVal message As String)
Console.WriteLine(message)
End Sub
End Module次に、Tim はこの文字列変数で拡張メソッドを呼び出す方法を示します:
demo.PrintToConsole();demo.PrintToConsole()PrintToConsoleメソッドを提案します。 これはstring型に追加された新しいメソッドです。
ティムはなぜdemo.PrintToConsole()を呼び出すことができるのかを説明します:
string型です。PrintToConsoleで拡張されました。PrintToConsoleメソッドにはパラメータが渡されていないように見えますが、ティムは暗黙のパラメータ渡しを指摘します - demo文字列が拡張メソッドへの最初のパラメータとして渡されます。
Timは、拡張メソッドは、定義よりも呼び出しのパラメータが1つ少ないことを強調しています。 これは、最初のパラメータ(拡張される型)が暗黙的であるためです。
ここでmessageが暗黙のパラメータです:
public static void PrintToConsole(this string message)<Extension()>
Public Sub PrintToConsole(ByVal message As String)最後に、PrintToConsoleメソッドが呼び出されると、文字列がコンソールに出力されます:
Console.WriteLine(message);Console.WriteLine(message)そのため、demo.PrintToConsole()を呼び出すと、"This is a demo"がコンソールに表示されます。
ティム・コリーは、拡張メソッドは、直接変更できないサードパーティのクラスであっても、あらゆる型を拡張できると説明しています。 たとえば、11:09にSimpleLoggerクラスを見てみましょう。
ここで、ティムはメッセージをコンソールに記録する仮想のサードパーティークラスSimpleLoggerを使用しています(11:09)。 このクラスには2つのメソッドがあります:
public class SimpleLogger
{
public void Log(string message)
{
Console.WriteLine(message);
}
public void Log(string message, string messageType)
{
Console.WriteLine($"{messageType}: {message}");
}
}Public Class SimpleLogger
Public Sub Log(message As String)
Console.WriteLine(message)
End Sub
Public Sub Log(message As String, messageType As String)
Console.WriteLine($"{messageType}: {message}")
End Sub
End Classメッセージタイプが単純な文字列であるため、矛盾が生じる可能性があり、これらの方法は理想的ではありません。 Timは、クラスを改善するために拡張メソッドを作成することを提案します。
拡張メソッドを使用すると、常に同じメッセージタイプと書式を使用することにより、コードの一貫性が保証されます。 ここで(12:40に)ティムは静的クラスExtendSimpleLoggerを作成します:
public static class ExtendSimpleLogger
{
public static void LogError(this SimpleLogger logger, string message)
{
logger.Log(message, "Error");
}
public static void LogWarning(this SimpleLogger logger, string message)
{
logger.Log(message, "Warning");
}
}Public Module ExtendSimpleLogger
<System.Runtime.CompilerServices.Extension>
Public Sub LogError(ByVal logger As SimpleLogger, ByVal message As String)
logger.Log(message, "Error")
End Sub
<System.Runtime.CompilerServices.Extension>
Public Sub LogWarning(ByVal logger As SimpleLogger, ByVal message As String)
logger.Log(message, "Warning")
End Sub
End Moduleそれを手に入れることで、(14:02に)彼はSimpleLoggerインスタンス上で拡張メソッドを呼び出すことができるようになりました:
SimpleLogger logger = new SimpleLogger();
logger.LogError("This is an error");
logger.LogWarning("This is a warning");Dim logger As New SimpleLogger()
logger.LogError("This is an error")
logger.LogWarning("This is a warning")このため、メッセージタイプは常に"エラー"と"警告"であることが保証されます。
Timは、エラーメッセージのコンソールテキストの色を設定する機能を追加し、目立つようにしました:
public static void LogError(this SimpleLogger logger, string message)
{
var defaultColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Red;
logger.Log(message, "Error");
Console.ForegroundColor = defaultColor;
}<Extension()>
Public Sub LogError(ByVal logger As SimpleLogger, ByVal message As String)
Dim defaultColor = Console.ForegroundColor
Console.ForegroundColor = ConsoleColor.Red
logger.Log(message, "Error")
Console.ForegroundColor = defaultColor
End Subティムは、このアプローチをオリジナルのLogメソッドを直接呼び出すのと比較し、不一致を引き起こす可能性があることを示しています:
logger.Log("Test error", "Error");
logger.Log("Another error", "ERROR");logger.Log("Test error", "Error")
logger.Log("Another error", "ERROR")このアプローチでは、誤字や一貫性のない書式が発生しがちです。
Timは、コードをより読みやすくするために、拡張メソッドをどのように連鎖させることができるかを示します:
public static void LogInfo(this SimpleLogger logger, string message)
{
logger.Log(message, "Info");
}
public static void SaveToDatabase(this SimpleLogger logger)
{
// Simulate saving to a database
}Public Sub LogInfo(ByVal logger As SimpleLogger, ByVal message As String)
logger.Log(message, "Info")
End Sub
Public Sub SaveToDatabase(ByVal logger As SimpleLogger)
' Simulate saving to a database
End Sub今、あなたはこれらの方法を連鎖させることができます:
logger.LogInfo("Information").SaveToDatabase();logger.LogInfo("Information").SaveToDatabase()これにより、ネストされたメソッド呼び出しに比べて、コードがより読みやすく、直感的になります:
SaveToDatabase(LogInfo(logger, "Information"));SaveToDatabase(LogInfo(logger, "Information"))ドット表記とチェーニングを使用することで、コードの意図が明確になり、入れ子が少なくなります。
20:13で、ティム・コーリーは、拡張メソッドは、サードパーティのライブラリなど、自分が所有していないクラスに機能を追加するのに理想的であると説明している。 これにより、元のコードを修正することなく、機能拡張を行うことができます。
また、Corey は、クラスに直接カップリングすることなく依存関係を導入するための拡張メソッドの使用についても強調しています。 たとえば、データベースのロジックを埋め込まずにデータベースの保存機能をPersonクラスに追加すること。
21:30から説明されるように、拡張メソッドはインターフェースにも適用でき、インターフェースを実装した複数のクラスが同じ機能を共有することを可能にする。 これにより、コードの再利用と簡素化が促進されます。
23:03で、ティム・コーリーは、特にプリミティブ型やマイクロソフトが提供する型では、乱雑さと複雑さを防ぐために、拡張メソッドを使いすぎないようにアドバイスしている。 これらのツールの使用は控えめにし、明確な利点がある場合にのみ使用してください。
24:54-25:40のセクションでは、Timは、既存の安定したコードを変更することなく、新しい機能を追加するために拡張メソッドを使用することにより、バグをもたらすリスクを低減し、オープン/クローズの原則を遵守することを強調しています。
拡張メソッドを論理的にグループ化し、別々の名前空間に配置することで、名前の衝突を避け、メンテナンスとデバッグを容易にします。
これで、メソッドの定義と呼び出し、パラメータと戻り値の処理、メソッドのオーバーロードの活用の基本を理解したことになります。 これにより、C#で堅牢かつ柔軟なアプリケーションを構築することができます。
ティム・コリーが説明する拡張メソッドは、既存の型を拡張し、コードをより読みやすく保守しやすくする強力な方法を提供します。 より詳細な洞察と実用的な例については、How To Create Extension Methods in C# に関するティム・コーリーのビデオ全編をご覧ください。
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!
Join our newsletter, you’ll get exclusive access on article updates. We value your privacy