|
■No90217 (猪マン さん) に返信
> 特に何か問題があったわけではないのですが、変数にメッソド名やプロパティ名を
> 入れて使いたい場合もあるかもしれないので、知っていれば便利かなと思って質問しました。
デリゲートを使うのが近そうな気がします。今はリンク切れとなって見ることができませんが、Microsoft の
C# のチュートリアルにデリゲートを説明したコードがあって、それが自分の PC に残ってましたので、ご参考
に貼っておきます。
4 つのサンプルを一つにまとめているので、コンパイル・実行するには使わない 3 つをコメントアウトするな
どしないとダメですので注意してください。
やりたいこととは違って役に立たなかったらスミマセン。
using System;
using System.Collections;
// デリゲートのチュートリアル
// C# のデリゲートは、C や C++ の関数ポインタと同じ。
// C や C++ の関数ポインタは静的関数だけを参照できるのに対し、デリゲートでは静的メソッドと
// インスタンスメソッドの両方を参照できる。
namespace Example1
{
// int 型の引数を一つ持つメソッドへの参照型を MyDelegate と定義
delegate void MyDelegate(int i);
// MyDelegate p; で参照型 p を宣言できる。
// new MyDelegate(Function) でメソッド Function への参照を生成できる。
class Program
{
// TaskADelegate を呼んで、その引数としてメソッド DelegateFunction への参照値を渡す
public static void Main()
{
TakesADelegate(new MyDelegate(DelegateFunction)); // DelegateFunction(21); と同じ
}
// ポインタ SomeFunction が指すメソッドを呼んで、それに引数として 21 を渡す
public static void TakesADelegate(MyDelegate SomeFunction)
{
SomeFunction(21);
}
public static void DelegateFunction(int i)
{
System.Console.WriteLine("Called by delegate with number: {0}.", i);
}
}
}
// 例2:デリゲートは静的メソッドとインスタンスメソッドの両方を参照できることの例。
namespace Example2
{
delegate void MyDelegate(); // 引数を持たないメソッドへの参照型を MyDelegate と定義
public class MyClass
{
public void InstanceMethod()
{
Console.WriteLine("A message from the instance method.");
}
static public void StaticMethod()
{
Console.WriteLine("A message from the static method.");
}
}
public class MainClass
{
static public void Main()
{
MyClass p = new MyClass();
MyDelegate d = new MyDelegate(p.InstanceMethod);
d(); // d はインスタンスメソッド p.InstanceMethos() への参照値を持つ。
// d() はメソッドそのもの
d = new MyDelegate(MyClass.StaticMethod); // 静的なので p.StaticMethod は不可
d(); // 静的メソッド MyClass.StaticMethod() を呼ぶ
}
}
}
// 例3:デリゲートの宣言方法、インスタンス化方法、および呼び出し方法を示す。
// デリゲートを使用すると、書店データベースとクライアントコードの機能の分担を適切に行うこと
// ができる。BookTextClient コードは、書籍の在庫状況や Booksore コードがペーパーバックを検
// 索する方法については関知しない。Bookstore コードは、ペーパーバックの検索後の処理について
// は関知しない。
namespace Bookstore
{
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;
}
}
// Book 型の引数を一つ持つメソッドへの参照型を ProcessBookDelegate と定義
public delegate void ProcessBookDelegate(Book book);
public class BookDB
{
ArrayList list = new ArrayList(); // データベース中のすべての本のリスト
// データベースに本を追加
public void AddBook(string title, string author, decimal price, bool paperBack)
{
list.Add(new Book(title, author, price, paperBack));
}
// データベース BookDB のリスト list にあるすべての本について、
// 本がペーパーバックなら引数 processBook が指す関数を呼ぶ
public void ProcessPaperbackBooks(ProcessBookDelegate processBook)
{
foreach (Book b in list)
{
if (b.Paperback)
processBook(b);
}
}
}
}
namespace BookTestClient
{
using Bookstore;
// 本の数量と価格合計および平均を求めるためのクラス
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 Test
{
static void PrintTitle(Book b)
{
Console.WriteLine(" {0}", b.Title);
}
static void Main()
{
// Book の配列からなる本のデータベースを作る。bookDB はデータベースを指す
BookDB bookDB = new BookDB();
AddBooks(bookDB);
Console.WriteLine("Paperback Book Titles:");
// メソッド ProcessPaperbackBooks に処置方法 PrintTitle を渡し bookDB を操作する
// (即ち、データベースの本がペーバーバックなら PrintTile する)
bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle));
// メソッド ProcessPaperbackBooks に処置方法 AddBookToTotal を渡し bookDB を操作する
// (即ち、データベースの本がペーバーバックなら数を数えて価格を合計に加える)
PriceTotaller totaller = new PriceTotaller();
bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(totaller.AddBookToTotal));
Console.WriteLine("Average Paperback Book Price: ${0:#.##}", totaller.AveragePrice());
}
// テスト用データベースを作るためのメソッド
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);
}
}
}
// 例4:デリゲートの結合方法を示す。
// デリゲートオブジェクトは "+" 演算子を使用して結合できる。結合されたデリゲートは、結合元の複数
// のデリゲートを呼び出す。結合できるのは同じ型のデリゲートだけである。結合されたデリゲートを "-"
// 演算子を使用して取り除くこともできる。
namespace Example4
{
delegate void MyDelegate(string s);
class MyClass
{
public static void Hello(string s)
{
Console.WriteLine(" Hello, {0}!", s);
}
public static void Goodbye(string s)
{
Console.WriteLine(" Goodbye, {0}!", s);
}
public static void Main()
{
MyDelegate a, b, c, d; // デリゲートの宣言
// a にメソッド Hello への参照値を代入
a = new MyDelegate(Hello);
// b にメソッド Goodbye への参照値を代入
b = new MyDelegate(Goodbye);
// a と b を結合して c に代入
c = a + b;
// c から a を取り除いて d に代入
d = c - a;
Console.WriteLine("Invoking delegate a:");
a("A");
Console.WriteLine("Invoking delegate b:");
b("B");
Console.WriteLine("Invoking delegate c:");
c("C");
Console.WriteLine("Invoking delegate d:");
d("D");
}
}
}
|