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
1時間9分11秒
C# の Delegate は強力な機能ですが、多くの開発者はその効果的な使い方に精通していません。 Tim Corey の"Delegates in C# - A practical demonstration, including Action and Func"というビデオでは、デリゲートとは何か、どのように使うのか、なぜ便利なのかを徹底的に説明しています。
この記事では、C#のデリゲートに関するTimの専門的な洞察を提供し、その使用方法と実用的なアプリケーションの明確な説明を提供します。 ショッピングカートシステムでの使用例などを交えながら、デリゲートがコードの柔軟性と効率性をどのように高めることができるかを学びます。
Timはデリゲートの概念を紹介し、C#におけるデリゲートのパワーと汎用性を強調します。 彼は、威圧的な専門用語がいくつかあるにもかかわらず、デリゲートの基礎はシンプルであると視聴者に保証する。 Timは、デリゲートを解明し、funcやactionのような特殊な型をカバーすることを目指しています。
Timは、デリゲートの使い方を説明するためにデモアプリケーションをセットアップします。 このソリューションには、コンソールUI、デモライブラリ、WinForm UIの3つのプロジェクトが含まれています。 最初は、コンソールUIとデモライブラリに焦点を当てます。
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleUI
{
class Program
{
static ShoppingCartModel cart = new ShoppingCartModel();
static void Main(string[] args)
{
PopulateCartWithDemoData();
Console.WriteLine($"The total for the cart is {cart.GenerateTotal():C2}");
Console.ReadLine();
}
private static void PopulateCartWithDemoData()
{
cart.Items.Add(new ProductModel { ItemName = "Cereal", Price = 3.63M });
cart.Items.Add(new ProductModel { ItemName = "Milk", Price = 2.95M });
cart.Items.Add(new ProductModel { ItemName = "Strawberries", Price = 7.51M });
cart.Items.Add(new ProductModel { ItemName = "Blueberries", Price = 6.75M });
}
}
}
public class ShoppingCartModel
{
public List<ProductModel> Items { get; set; } = new List<ProductModel>();
public decimal GenerateTotal()
{
decimal subtotal = Items.Sum(x => x.Price);
if (subtotal > 100)
{
return subtotal * 0.80M;
}
else if (subtotal > 50)
{
return subtotal * 0.85M;
}
else if (subtotal > 10)
{
return subtotal * 0.90M;
}
else
{
return subtotal;
}
}
}
public class ProductModel
{
public string ItemName { get; set; }
public decimal Price { get; set; }
}Imports System
Imports System.Collections.Generic
Imports System.Linq
Namespace ConsoleUI
Class Program
Private Shared cart As New ShoppingCartModel()
Shared Sub Main(args As String())
PopulateCartWithDemoData()
Console.WriteLine($"The total for the cart is {cart.GenerateTotal():C2}")
Console.ReadLine()
End Sub
Private Shared Sub PopulateCartWithDemoData()
cart.Items.Add(New ProductModel With {.ItemName = "Cereal", .Price = 3.63D})
cart.Items.Add(New ProductModel With {.ItemName = "Milk", .Price = 2.95D})
cart.Items.Add(New ProductModel With {.ItemName = "Strawberries", .Price = 7.51D})
cart.Items.Add(New ProductModel With {.ItemName = "Blueberries", .Price = 6.75D})
End Sub
End Class
End Namespace
Public Class ShoppingCartModel
Public Property Items As List(Of ProductModel) = New List(Of ProductModel)()
Public Function GenerateTotal() As Decimal
Dim subtotal As Decimal = Items.Sum(Function(x) x.Price)
If subtotal > 100 Then
Return subtotal * 0.80D
ElseIf subtotal > 50 Then
Return subtotal * 0.85D
ElseIf subtotal > 10 Then
Return subtotal * 0.90D
Else
Return subtotal
End If
End Function
End Class
Public Class ProductModel
Public Property ItemName As String
Public Property Price As Decimal
End ClassTimは、デモアプリケーションの構造と機能を説明します:
ショッピングカートモデル:アイテム (ProductModel) のリストでショッピングカートを表現し、小計に基づく割引で合計金額を計算します。
商品モデル:名前と価格のプロパティを持つ個々のアイテムを表します。
コンソールアプリケーション:カートにデモデータを入力し、合計を計算し、表示します。
Timは、GenerateTotalメソッドの割引ロジックを説明し、どのように小計が適用される割引を決定するかを説明します:
ティムは、計算と割引のロジックを示すためにブレークポイントを使用し、視聴者がデリゲートを導入する前に基礎を理解していることを確認します。
このセクションでは、Tim CoreyがC#におけるデリゲートの概念に飛び込み、デリゲートがどのように機能するかを説明し、実用的なコード例でその使い方を実演します。
Timは、デリゲートは基本的にメソッドをパラメータとして渡す方法であると説明します。 変数やプロパティを渡す代わりにメソッドを渡すことで、より柔軟で再利用可能なコードを実現します。
ここでは、Timがデリゲートを作成し使用するプロセスをどのように説明しているかを紹介します:
1.デリゲートを定義する:
public delegate void MentionDiscount(decimal subtotal);Public Delegate Sub MentionDiscount(subtotal As Decimal)2.メソッドでデリゲートを使う:
public decimal GenerateTotal(MentionDiscount mentionDiscount)
{
decimal subtotal = Items.Sum(x => x.Price);
// Call a method passed as a delegate
mentionDiscount(subtotal);
if (subtotal > 100)
{
return subtotal * 0.80M;
}
else if (subtotal > 50)
{
return subtotal * 0.85M;
}
else if (subtotal > 10)
{
return subtotal * 0.90M;
}
else
{
return subtotal;
}
}
3.デリゲートに渡すメソッドを作成する:
private static void SubtotalAlert(decimal subtotal)
{
Console.WriteLine($"The subtotal is {subtotal:C2}");
}
4.GenerateTotalメソッドの呼び出し:
class Program
{
static ShoppingCartModel cart = new ShoppingCartModel();
static void Main(string[] args)
{
PopulateCartWithDemoData();
Console.WriteLine($"The total for the cart is {cart.GenerateTotal(SubtotalAlert):C2}");
Console.ReadLine();
}
private static void PopulateCartWithDemoData()
{
cart.Items.Add(new ProductModel { ItemName = "Cereal", Price = 3.63M });
cart.Items.Add(new ProductModel { ItemName = "Milk", Price = 2.95M });
cart.Items.Add(new ProductModel { ItemName = "Strawberries", Price = 7.51M });
cart.Items.Add(new ProductModel { ItemName = "Blueberries", Price = 6.75M });
}
}
Timは、デリゲートがどのように動作するかを示すためにアプリケーションを実行します。 コンソール出力は、カートの小計と合計を示し、SubtotalAlert メソッドがデリゲート経由で正常に渡され実行されたことを示しています。

ティム・コーリーは次に、C#におけるfuncとactionのデリゲートの使い方を説明します。 これは、ジェネリックスのデリゲート使用を簡素化するためにMicrosoftによって提供された特別なタイプのデリゲートです。
Timは、よくある問題である、GenerateTotalメソッドにハードコードされた割引ロジックに注目しています。 このアプローチは柔軟性に欠け、割引ルールが変更されるたびにコードの変更、再コンパイル、再デプロイメントが必要になります。
public decimal GenerateTotal()
{
decimal subtotal = Items.Sum(x => x.Price);
if (subtotal > 100)
{
return subtotal * 0.80M;
}
else if (subtotal > 50)
{
return subtotal * 0.85M;
}
else if (subtotal > 10)
{
return subtotal * 0.90M;
}
else
{
return subtotal;
}
}Public Function GenerateTotal() As Decimal
Dim subtotal As Decimal = Items.Sum(Function(x) x.Price)
If subtotal > 100 Then
Return subtotal * 0.80D
ElseIf subtotal > 50 Then
Return subtotal * 0.85D
ElseIf subtotal > 10 Then
Return subtotal * 0.90D
Else
Return subtotal
End If
End FunctionTimは、ハードコードされた割引の問題に対処するためにfuncデリゲートを紹介します。 funcデリゲートは、戻り値の型と最大16個の入力パラメータを持つメソッドシグネチャを表す一般的なデリゲートです。
1.Funcデリゲートの定義:
public decimal GenerateTotal(Func<List<ProductModel>, decimal, decimal> calculateDiscountedTotal)
{
decimal subtotal = Items.Sum(x => x.Price);
MentionDiscount(subtotal);
return calculateDiscountedTotal(Items, subtotal);
}
2.割引計算方法の作成:
private static decimal CalculateLevelDiscount(List<ProductModel> items, decimal subtotal)
{
if (subtotal > 100)
{
return subtotal * 0.80M;
}
else if (subtotal > 50)
{
return subtotal * 0.85M;
}
else if (subtotal > 10)
{
return subtotal * 0.90M;
}
else
{
return subtotal;
}
}
3.メソッドを Func Delegate に渡す:
class Program
{
static ShoppingCartModel cart = new ShoppingCartModel();
static void Main(string[] args)
{
PopulateCartWithDemoData();
Console.WriteLine($"The total for the cart is {cart.GenerateTotal(CalculateLevelDiscount):C2}");
Console.ReadLine();
}
private static void PopulateCartWithDemoData()
{
cart.Items.Add(new ProductModel { ItemName = "Cereal", Price = 3.63M });
cart.Items.Add(new ProductModel { ItemName = "Milk", Price = 2.95M });
cart.Items.Add(new ProductModel { ItemName = "Strawberries", Price = 7.51M });
cart.Items.Add(new ProductModel { ItemName = "Blueberries", Price = 6.75M });
}
private static decimal CalculateLevelDiscount(List<ProductModel> items, decimal subtotal)
{
if (subtotal > 100)
{
return subtotal * 0.80M;
}
else if (subtotal > 50)
{
return subtotal * 0.85M;
}
else if (subtotal > 10)
{
return subtotal * 0.90M;
}
else
{
return subtotal;
}
}
}
Timは、修正したアプリケーションを実演し、それが正しく機能し、提供されたロジックに基づいて動的に割引を計算することを示します。

Tim は、カスタムデリゲートと func デリゲートを比較しています:
委任:シグネチャの明確な定義を必要とし、明確な文書と構造を提供します。
Func:より簡潔ですが、入力と出力の型を毎回指定する必要があり、明確でない場合があります。
どちらのアプローチも柔軟性がありますが、特定のユースケースとアプリケーションの複雑さによって選択します。
ティム・コリーは、デリゲートの使用に関するよくある質問に答えています:すべての作業が他の場所で行われているように見えるのに、なぜデリゲートを持つのですか?
ティムは、デリゲートの目的はコードに柔軟性と拡張性を持たせることだと説明する。 ShoppingCartModel クラスの GenerateTotal メソッドは、単に割引を計算するだけではありません。 また、在庫の有無の確認、カートの内容の検証、その他のビジネスロジックなどのタスクを処理することもあります。 デリゲートを使用すると、コアメソッドを変更することなく、独自のタスクやカスタム動作のために特定のメソッドを渡すことができます。 これにより、コードがよりモジュール化され、保守が容易になります。
デリゲートは、以下のような場面で特に役立ちます:
Timは、C#のデリゲートのもう一つの特別なタイプであるActionデリゲートを紹介します。 ActionデリゲートはFuncに似ていますが、値を返しません(つまりvoidを返します)。
1.アクションデリゲートの作成:
public decimal GenerateTotal(Func<List<ProductModel>, decimal, decimal> calculateDiscountedTotal, Action<string> tellUserWeAreDiscounting)
{
decimal subtotal = Items.Sum(x => x.Price);
MentionSubtotal(subtotal);
tellUserWeAreDiscounting("We are applying your discount.");
return calculateDiscountedTotal(Items, subtotal);
}
2.アラートメソッドを作成する:
private static void AlertUser(string message)
{
Console.WriteLine(message);
}
3.アクション・デレゲートにメソッドを渡す:
class Program
{
static ShoppingCartModel cart = new ShoppingCartModel();
static void Main(string[] args)
{
PopulateCartWithDemoData();
Console.WriteLine($"The total for the cart is {cart.GenerateTotal(CalculateLevelDiscount, AlertUser):C2}");
Console.ReadLine();
}
private static void PopulateCartWithDemoData()
{
cart.Items.Add(new ProductModel { ItemName = "Cereal", Price = 3.63M });
cart.Items.Add(new ProductModel { ItemName = "Milk", Price = 2.95M });
cart.Items.Add(new ProductModel { ItemName = "Strawberries", Price = 7.51M });
cart.Items.Add(new ProductModel { ItemName = "Blueberries", Price = 6.75M });
}
private static decimal CalculateLevelDiscount(List<ProductModel> items, decimal subtotal)
{
if (subtotal > 100)
{
return subtotal * 0.80M;
}
else if (subtotal > 50)
{
return subtotal * 0.85M;
}
else if (subtotal > 10)
{
return subtotal * 0.90M;
}
else
{
return subtotal;
}
}
private static void AlertUser(string message)
{
Console.WriteLine(message);
}
}
Timは、名前を付けずにその場でメソッドを定義できる無名メソッドの使い方を紹介します。
1.匿名メソッドの定義:
class Program
{
static ShoppingCartModel cart = new ShoppingCartModel();
static void Main(string[] args)
{
PopulateCartWithDemoData();
Console.WriteLine($"The total for the cart is {cart.GenerateTotal((items, subtotal) =>
{
if (subtotal > 100) return subtotal * 0.80M;
else if (subtotal > 50) return subtotal * 0.85M;
else if (subtotal > 10) return subtotal * 0.90M;
else return subtotal;
},
(message) => Console.WriteLine(message)):C2}");
Console.ReadLine();
}
private static void PopulateCartWithDemoData()
{
cart.Items.Add(new ProductModel { ItemName = "Cereal", Price = 3.63M });
cart.Items.Add(new ProductModel { ItemName = "Milk", Price = 2.95M });
cart.Items.Add(new ProductModel { ItemName = "Strawberries", Price = 7.51M });
cart.Items.Add(new ProductModel { ItemName = "Blueberries", Price = 6.75M });
}
}
2.構文を理解する:
=> 演算子(ラムダ式)を使用して、メソッド本体を直接インラインで定義します。Func、Action、匿名メソッドを含むデリゲートを使用することで、開発者はより動的でモジュール化されたコードを作成することができ、柔軟で再利用可能なコンポーネントを作成することができます。
このセグメントでは、Tim CoreyがWinFormsアプリケーションにデリゲートの使用を拡張することで、デリゲートのパワーを実証します。 これは、デリゲートがさまざまなユーザーインターフェイス(UI)のコンテキストでどのように異なる動作を促進できるかを強調するものです。
1.2つのボタンを持つWinForm UI:
フォームには2つのボタンがあり、1つはメッセージボックスのデモ用、もう1つはテキストボックスのデモ用です。
ShoppingCartModel と、それにデモデータを入力するメソッドも含まれています。
public partial class Dashboard : Form
{
ShoppingCartModel cart = new ShoppingCartModel();
public Dashboard()
{
InitializeComponent();
PopulateCartWithDemoData();
}
private void PopulateCartWithDemoData()
{
cart.Items.Add(new ProductModel { ItemName = "Cereal", Price = 3.63M });
cart.Items.Add(new ProductModel { ItemName = "Milk", Price = 2.95M });
cart.Items.Add(new ProductModel { ItemName = "Strawberries", Price = 7.51M });
cart.Items.Add(new ProductModel { ItemName = "Blueberries", Price = 6.75M });
}
private void messageBoxDemoButton_Click(object sender, EventArgs e)
{
decimal total = cart.GenerateTotal(SubtotalAlert, CalculateLevelDiscount, PrintOutDiscountAlert);
MessageBox.Show($"The total is {total:C2}");
}
private void textBoxDemoButton_Click(object sender, EventArgs e)
{
// Code for TextBox demo will go here
}
}Public Partial Class Dashboard
Inherits Form
Private cart As New ShoppingCartModel()
Public Sub New()
InitializeComponent()
PopulateCartWithDemoData()
End Sub
Private Sub PopulateCartWithDemoData()
cart.Items.Add(New ProductModel With {.ItemName = "Cereal", .Price = 3.63D})
cart.Items.Add(New ProductModel With {.ItemName = "Milk", .Price = 2.95D})
cart.Items.Add(New ProductModel With {.ItemName = "Strawberries", .Price = 7.51D})
cart.Items.Add(New ProductModel With {.ItemName = "Blueberries", .Price = 6.75D})
End Sub
Private Sub messageBoxDemoButton_Click(sender As Object, e As EventArgs) Handles messageBoxDemoButton.Click
Dim total As Decimal = cart.GenerateTotal(AddressOf SubtotalAlert, AddressOf CalculateLevelDiscount, AddressOf PrintOutDiscountAlert)
MessageBox.Show($"The total is {total:C2}")
End Sub
Private Sub textBoxDemoButton_Click(sender As Object, e As EventArgs) Handles textBoxDemoButton.Click
' Code for TextBox demo will go here
End Sub
End Class1.PrintOutDiscountAlert:
private void PrintOutDiscountAlert(string message)
{
MessageBox.Show(message);
}
2.SubtotalAlert:
private void SubtotalAlert(decimal subtotal)
{
MessageBox.Show($"The subtotal is {subtotal:C2}");
}
3.CalculateLevelDiscount:
private decimal CalculateLevelDiscount(List<ProductModel> items, decimal subtotal)
{
if (items.Count > 3)
{
return subtotal - 3M;
}
return subtotal - items.Count;
}
1.ボタンのクリックイベントでデリゲートを使う:
messageBoxDemoButton_Click メソッドは、デリゲートをGenerateTotalメソッドに渡し、メッセージボックスを使用して結果を処理する方法を示します。private void messageBoxDemoButton_Click(object sender, EventArgs e)
{
decimal total = cart.GenerateTotal(SubtotalAlert, CalculateLevelDiscount, PrintOutDiscountAlert);
MessageBox.Show($"The total is {total:C2}");
}
2.アプリケーションの実行:

Tim Coreyは、C#におけるデリゲートについて、その基本、高度な使用法、ショッピングカートでのデリゲートの使用などの実用的な例を取り上げながら、わかりやすく説明しています。 Func、Action、匿名メソッドなど、デリゲートが柔軟で再利用可能なコードをどのように実現するかを示している。 ビデオの全文をご覧になり、プロジェクトでデリゲートを効果的に適用する方法を学んでください!
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