デリゲートを宣言し、インスタンス化して使用する方法 (C# プログラミング ガイド)How to declare, instantiate, and use a Delegate (C# Programming Guide)

C# 1.0 以降では、次の例に示すようにデリゲートを宣言できます。In C# 1.0 and later, delegates can be declared as shown in the following example.

// Declare a delegate.
delegate void Del(string str);

// Declare a method with the same signature as the delegate.
static void Notify(string name)
{
    Console.WriteLine($"Notification received for: {name}");
}
// Create an instance of the delegate.
Del del1 = new Del(Notify);

C# 2.0 では、次の例に示すように、上記の宣言をより簡単に記述できます。C# 2.0 provides a simpler way to write the previous declaration, as shown in the following example.

// C# 2.0 provides a simpler way to declare an instance of Del.
Del del2 = Notify;

C# 2.0 以降では、次の例に示すように、匿名メソッドを使用してデリゲートの宣言と初期化を行うこともできます。In C# 2.0 and later, it is also possible to use an anonymous method to declare and initialize a delegate, as shown in the following example.

// Instantiate Del by using an anonymous method.
Del del3 = delegate(string name)
    { Console.WriteLine($"Notification received for: {name}"); };

C# 3.0 以降では、次の例に示すように、ラムダ式を使用してデリゲートの宣言とインスタンス化を行うこともできます。In C# 3.0 and later, delegates can also be declared and instantiated by using a lambda expression, as shown in the following example.

// Instantiate Del by using a lambda expression.
Del del4 = name =>  { Console.WriteLine($"Notification received for: {name}"); };

詳細については、「ラムダ式」を参照してください。For more information, see Lambda Expressions.

次の例で、デリゲートの宣言、インスタンス化、および使用の方法について説明します。The following example illustrates declaring, instantiating, and using a delegate. BookDB クラスにより、書籍のデータベースを保持する書店データベースをカプセル化します。The BookDB class encapsulates a bookstore database that maintains a database of books. これは、データベース内にあるすべてのペーパーバックを検索し、各ペーパーバックに対してデリゲートを呼び出す ProcessPaperbackBooks メソッドを公開します。It exposes a method, ProcessPaperbackBooks, which finds all paperback books in the database and calls a delegate for each one. 使用する delegate 型には ProcessBookDelegate という名前を付けます。The delegate type that is used is named ProcessBookDelegate. Test クラスでは、このクラスを使用してペーパーバックのタイトルと平均価格を出力します。The Test class uses this class to print the titles and average price of the paperback books.

デリゲートを使用することで、書店データベースとクライアント コードの機能を適切に分離しやすくなります。The use of delegates promotes good separation of functionality between the bookstore database and the client code. クライアント コードからは、書籍の格納方法や書店コードでのペーパーバックの検索方法はわかりません。The client code has no knowledge of how the books are stored or how the bookstore code finds paperback books. 書店コードからは、検索後にペーパーバックに対して行われる処理はわかりません。The bookstore code has no knowledge of what processing is performed on the paperback books after it finds them.

Example

// A set of classes for handling a bookstore:
namespace Bookstore
{
    using System.Collections;

    // Describes a book in the book list:
    public struct Book
    {
        public string Title;        // Title of the book.
        public string Author;       // Author of the book.
        public decimal Price;       // Price of the book.
        public bool Paperback;      // Is it paperback?

        public Book(string title, string author, decimal price, bool paperBack)
        {
            Title = title;
            Author = author;
            Price = price;
            Paperback = paperBack;
        }
    }

    // Declare a delegate type for processing a book:
    public delegate void ProcessBookDelegate(Book book);

    // Maintains a book database.
    public class BookDB
    {
        // List of all books in the database:
        ArrayList list = new ArrayList();

        // Add a book to the database:
        public void AddBook(string title, string author, decimal price, bool paperBack)
        {
            list.Add(new Book(title, author, price, paperBack));
        }

        // Call a passed-in delegate on each paperback book to process it:
        public void ProcessPaperbackBooks(ProcessBookDelegate processBook)
        {
            foreach (Book b in list)
            {
                if (b.Paperback)
                    // Calling the delegate:
                    processBook(b);
            }
        }
    }
}

// Using the Bookstore classes:
namespace BookTestClient
{
    using Bookstore;

    // Class to total and average prices of books:
    class PriceTotaller
    {
        int countBooks = 0;
        decimal priceBooks = 0.0m;

        internal void AddBookToTotal(Book book)
        {
            countBooks += 1;
            priceBooks += book.Price;
        }

        internal decimal AveragePrice()
        {
            return priceBooks / countBooks;
        }
    }

    // Class to test the book database:
    class Test
    {
        // Print the title of the book.
        static void PrintTitle(Book b)
        {
            Console.WriteLine($"   {b.Title}");
        }

        // Execution starts here.
        static void Main()
        {
            BookDB bookDB = new BookDB();

            // Initialize the database with some books:
            AddBooks(bookDB);

            // Print all the titles of paperbacks:
            Console.WriteLine("Paperback Book Titles:");

            // Create a new delegate object associated with the static
            // method Test.PrintTitle:
            bookDB.ProcessPaperbackBooks(PrintTitle);

            // Get the average price of a paperback by using
            // a PriceTotaller object:
            PriceTotaller totaller = new PriceTotaller();

            // Create a new delegate object associated with the nonstatic
            // method AddBookToTotal on the object totaller:
            bookDB.ProcessPaperbackBooks(totaller.AddBookToTotal);

            Console.WriteLine("Average Paperback Book Price: ${0:#.##}",
                    totaller.AveragePrice());
        }

        // Initialize the book database with some test books:
        static void AddBooks(BookDB bookDB)
        {
            bookDB.AddBook("The C Programming Language", "Brian W. Kernighan and Dennis M. Ritchie", 19.95m, true);
            bookDB.AddBook("The Unicode Standard 2.0", "The Unicode Consortium", 39.95m, true);
            bookDB.AddBook("The MS-DOS Encyclopedia", "Ray Duncan", 129.95m, false);
            bookDB.AddBook("Dogbert's Clues for the Clueless", "Scott Adams", 12.00m, true);
        }
    }
}
/* Output:
Paperback Book Titles:
   The C Programming Language
   The Unicode Standard 2.0
   Dogbert's Clues for the Clueless
Average Paperback Book Price: $23.97
*/

信頼性の高いプログラミングRobust Programming

  • デリゲートを宣言する。Declaring a delegate.

    次のステートメントで、新しいデリゲート型を宣言します。The following statement declares a new delegate type.

    public delegate void ProcessBookDelegate(Book book);
    

    各デリゲート型は、引数の数と型、およびデリゲートでカプセル化可能なメソッドの戻り値の型を示します。Each delegate type describes the number and types of the arguments, and the type of the return value of methods that it can encapsulate. 引数型または戻り値型のセットが新しく必要になった場合は、常に新しいデリゲート型を宣言する必要があります。Whenever a new set of argument types or return value type is needed, a new delegate type must be declared.

  • デリゲートをインスタンス化する。Instantiating a delegate.

    デリゲート型の宣言後、デリゲート オブジェクトを作成して特定のメソッドに関連付ける必要があります。After a delegate type has been declared, a delegate object must be created and associated with a particular method. 先の例では、次の例に示すように PrintTitle メソッドを ProcessPaperbackBooks メソッドに渡すことでこの操作を行っています。In the previous example, you do this by passing the PrintTitle method to the ProcessPaperbackBooks method as in the following example:

    bookDB.ProcessPaperbackBooks(PrintTitle);
    

    これにより、静的 メソッド Test.PrintTitle に関連付けられた新しいデリゲート オブジェクトが作成されます。This creates a new delegate object associated with the static method Test.PrintTitle. 同様に、次の例で示すようにオブジェクト totaller の非静的メソッド AddBookToTotal も渡しています。Similarly, the non-static method AddBookToTotal on the object totaller is passed as in the following example:

    bookDB.ProcessPaperbackBooks(totaller.AddBookToTotal);
    

    どちらの場合でも、新しいデリゲート オブジェクトが ProcessPaperbackBooks メソッドに渡されます。In both cases a new delegate object is passed to the ProcessPaperbackBooks method.

    デリゲート オブジェクトは不変であるため、関連付けられているメソッドを、デリゲートの作成後に変更することはできません。After a delegate is created, the method it is associated with never changes; delegate objects are immutable.

  • デリゲートを呼び出す。Calling a delegate.

    デリゲート オブジェクトを作成したら、通常は、そのデリゲートを呼び出す別のコードにデリゲート オブジェクトを渡します。After a delegate object is created, the delegate object is typically passed to other code that will call the delegate. デリゲート オブジェクトを呼び出すときには、デリゲートに渡す引数を、デリゲート オブジェクト名の後ろにかっこで囲んで付けます。A delegate object is called by using the name of the delegate object, followed by the parenthesized arguments to be passed to the delegate. デリゲートの呼び出しの例を次に示します。Following is an example of a delegate call:

    processBook(b);
    

    デリゲートは、この例に示すように同期的に呼び出すことも、BeginInvoke メソッドおよび EndInvoke メソッドを使用して非同期的に呼び出すこともできます。A delegate can be either called synchronously, as in this example, or asynchronously by using BeginInvoke and EndInvoke methods.

関連項目See also