teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

追記

2019/09/20 09:04

投稿

退会済みユーザー
answer CHANGED
@@ -8,4 +8,241 @@
8
8
 
9
9
  > ProductGT10の引数がどのように決定されているのか仕組みがわかりません
10
10
 
11
- 上の説明によれば、Find<T> メソッドは、第 1 引数として渡された配列 Points[] の各要素 Point を、配列の先頭から最後まで順番に、第 2 引数として渡されたデリゲートを通じで ProductGT10 メソッドに引数として渡し、ProductGT10 メソッドが true を返した時点で作業を終了して、その時の Point を Find<T> メソッドの戻り値として返しているいるということです。
11
+ 上の説明によれば、Find<T> メソッドは、第 1 引数として渡された配列 Points[] の各要素 Point を、配列の先頭から最後まで順番に、第 2 引数として渡されたデリゲートを通じで ProductGT10 メソッドに引数として渡し、ProductGT10 メソッドが true を返した時点で作業を終了して、その時の Point を Find<T> メソッドの戻り値として返しているということです。
12
+
13
+ **【追記】**
14
+
15
+ 質問者さんの疑問は Array.FInd<T> メソッドよりも C# のデリゲートとは何かということのようにも思えますので、自分的に分かりやすかった Microsoft のチュートリアルのコードを貼っておきます。これを読めばデリゲートの基本は分かるのではないかと思います。
16
+
17
+ この記事は今はもうリンク切れになていて見ることができないのが残念。
18
+
19
+ ```
20
+ using System;
21
+ using System.Collections;
22
+
23
+ // デリゲートのチュートリアル
24
+ // C# のデリゲートは、C や C++ の関数ポインタと同じ。
25
+ // C や C++ の関数ポインタは静的関数だけを参照できるのに対し、デリゲートでは静的メソッドと
26
+ // インスタンスメソッドの両方を参照できる。
27
+
28
+ namespace Example1
29
+ {
30
+ // int 型の引数を一つ持つメソッドへの参照型を MyDelegate と定義
31
+ delegate void MyDelegate(int i);
32
+
33
+ // MyDelegate p; で参照型 p を宣言できる。
34
+ // new MyDelegate(Function) でメソッド Function への参照を生成できる。
35
+
36
+ class Program
37
+ {
38
+ // TaskADelegate を呼んで、その引数としてメソッド DelegateFunction への参照値を渡す
39
+ public static void Main()
40
+ {
41
+ TakesADelegate(new MyDelegate(DelegateFunction)); // DelegateFunction(21); と同じ
42
+ }
43
+
44
+ // ポインタ SomeFunction が指すメソッドを呼んで、それに引数として 21 を渡す
45
+ public static void TakesADelegate(MyDelegate SomeFunction)
46
+ {
47
+ SomeFunction(21);
48
+ }
49
+
50
+ public static void DelegateFunction(int i)
51
+ {
52
+ System.Console.WriteLine("Called by delegate with number: {0}.", i);
53
+ }
54
+ }
55
+ }
56
+
57
+
58
+ // 例2:デリゲートは静的メソッドとインスタンスメソッドの両方を参照できることの例。
59
+ namespace Example2
60
+ {
61
+ delegate void MyDelegate(); // 引数を持たないメソッドへの参照型を MyDelegate と定義
62
+
63
+ public class MyClass
64
+ {
65
+ public void InstanceMethod()
66
+ {
67
+ Console.WriteLine("A message from the instance method.");
68
+ }
69
+
70
+ static public void StaticMethod()
71
+ {
72
+ Console.WriteLine("A message from the static method.");
73
+ }
74
+ }
75
+
76
+ public class MainClass
77
+ {
78
+ static public void Main()
79
+ {
80
+ MyClass p = new MyClass();
81
+
82
+ MyDelegate d = new MyDelegate(p.InstanceMethod);
83
+ d(); // d はインスタンスメソッド p.InstanceMethos() への参照値を持つ。
84
+ // d() はメソッドそのもの
85
+
86
+ d = new MyDelegate(MyClass.StaticMethod); // 静的なので p.StaticMethod は不可
87
+ d(); // 静的メソッド MyClass.StaticMethod() を呼ぶ
88
+ }
89
+ }
90
+ }
91
+
92
+ // 例3:デリゲートの宣言方法、インスタンス化方法、および呼び出し方法を示す。
93
+ // デリゲートを使用すると、書店データベースとクライアントコードの機能の分担を適切に行うこと
94
+ // ができる。BookTextClient コードは、書籍の在庫状況や Booksore コードがペーパーバックを検
95
+ // 索する方法については関知しない。Bookstore コードは、ペーパーバックの検索後の処理について
96
+ // は関知しない。
97
+ namespace Bookstore
98
+ {
99
+ public struct Book
100
+ {
101
+ public string Title; // Title of the book.
102
+ public string Author; // Author of the book.
103
+ public decimal Price; // Price of the book.
104
+ public bool Paperback; // Is it paperback?
105
+
106
+ public Book(string title, string author, decimal price, bool paperBack)
107
+ {
108
+ Title = title;
109
+ Author = author;
110
+ Price = price;
111
+ Paperback = paperBack;
112
+ }
113
+ }
114
+
115
+ // Book 型の引数を一つ持つメソッドへの参照型を ProcessBookDelegate と定義
116
+ public delegate void ProcessBookDelegate(Book book);
117
+
118
+ public class BookDB
119
+ {
120
+ ArrayList list = new ArrayList(); // データベース中のすべての本のリスト
121
+
122
+ // データベースに本を追加
123
+ public void AddBook(string title, string author, decimal price, bool paperBack)
124
+ {
125
+ list.Add(new Book(title, author, price, paperBack));
126
+ }
127
+
128
+ // データベース BookDB のリスト list にあるすべての本について、
129
+ // 本がペーパーバックなら引数 processBook が指す関数を呼ぶ
130
+ public void ProcessPaperbackBooks(ProcessBookDelegate processBook)
131
+ {
132
+ foreach (Book b in list)
133
+ {
134
+ if (b.Paperback)
135
+ processBook(b);
136
+ }
137
+ }
138
+ }
139
+ }
140
+
141
+ namespace BookTestClient
142
+ {
143
+ using Bookstore;
144
+
145
+ // 本の数量と価格合計および平均を求めるためのクラス
146
+ class PriceTotaller
147
+ {
148
+ int countBooks = 0;
149
+ decimal priceBooks = 0.0m;
150
+
151
+ internal void AddBookToTotal(Book book)
152
+ {
153
+ countBooks += 1;
154
+ priceBooks += book.Price;
155
+ }
156
+
157
+ internal decimal AveragePrice()
158
+ {
159
+ return priceBooks / countBooks;
160
+ }
161
+ }
162
+
163
+ class Test
164
+ {
165
+ static void PrintTitle(Book b)
166
+ {
167
+ Console.WriteLine(" {0}", b.Title);
168
+ }
169
+
170
+ static void Main()
171
+ {
172
+ // Book の配列からなる本のデータベースを作る。bookDB はデータベースを指す
173
+ BookDB bookDB = new BookDB();
174
+ AddBooks(bookDB);
175
+
176
+ Console.WriteLine("Paperback Book Titles:");
177
+
178
+ // メソッド ProcessPaperbackBooks に処置方法 PrintTitle を渡し bookDB を操作する
179
+ // (即ち、データベースの本がペーバーバックなら PrintTile する)
180
+ bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle));
181
+
182
+ // メソッド ProcessPaperbackBooks に処置方法 AddBookToTotal を渡し bookDB を操作する
183
+ // (即ち、データベースの本がペーバーバックなら数を数えて価格を合計に加える)
184
+ PriceTotaller totaller = new PriceTotaller();
185
+ bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(totaller.AddBookToTotal));
186
+ Console.WriteLine("Average Paperback Book Price: ${0:#.##}", totaller.AveragePrice());
187
+ }
188
+
189
+ // テスト用データベースを作るためのメソッド
190
+ static void AddBooks(BookDB bookDB)
191
+ {
192
+ bookDB.AddBook("The C Programming Language",
193
+ "Brian W. Kernighan and Dennis M. Ritchie", 19.95m, true);
194
+ bookDB.AddBook("The Unicode Standard 2.0",
195
+ "The Unicode Consortium", 39.95m, true);
196
+ bookDB.AddBook("The MS-DOS Encyclopedia",
197
+ "Ray Duncan", 129.95m, false);
198
+ bookDB.AddBook("Dogbert's Clues for the Clueless",
199
+ "Scott Adams", 12.00m, true);
200
+ }
201
+ }
202
+ }
203
+
204
+ // 例4:デリゲートの結合方法を示す。
205
+ // デリゲートオブジェクトは "+" 演算子を使用して結合できる。結合されたデリゲートは、結合元の複数
206
+ // のデリゲートを呼び出す。結合できるのは同じ型のデリゲートだけである。結合されたデリゲートを "-"
207
+ // 演算子を使用して取り除くこともできる。
208
+ namespace Example4
209
+ {
210
+ delegate void MyDelegate(string s);
211
+
212
+ class MyClass
213
+ {
214
+ public static void Hello(string s)
215
+ {
216
+ Console.WriteLine(" Hello, {0}!", s);
217
+ }
218
+
219
+ public static void Goodbye(string s)
220
+ {
221
+ Console.WriteLine(" Goodbye, {0}!", s);
222
+ }
223
+
224
+ public static void Main()
225
+ {
226
+ MyDelegate a, b, c, d; // デリゲートの宣言
227
+
228
+ // a にメソッド Hello への参照値を代入
229
+ a = new MyDelegate(Hello);
230
+ // b にメソッド Goodbye への参照値を代入
231
+ b = new MyDelegate(Goodbye);
232
+ // a と b を結合して c に代入
233
+ c = a + b;
234
+ // c から a を取り除いて d に代入
235
+ d = c - a;
236
+
237
+ Console.WriteLine("Invoking delegate a:");
238
+ a("A");
239
+ Console.WriteLine("Invoking delegate b:");
240
+ b("B");
241
+ Console.WriteLine("Invoking delegate c:");
242
+ c("C");
243
+ Console.WriteLine("Invoking delegate d:");
244
+ d("D");
245
+ }
246
+ }
247
+ }
248
+ ```

2

追記&訂正

2019/09/20 09:04

投稿

退会済みユーザー
answer CHANGED
@@ -8,4 +8,4 @@
8
8
 
9
9
  > ProductGT10の引数がどのように決定されているのか仕組みがわかりません
10
10
 
11
- 上の説明によれば、Find<T> メソッド ProductGT10 メソッドの引数として Points[] の各要素 Ponit を順に渡しているということです。
11
+ 上の説明によれば、Find<T> メソッドは、第 1 引数として渡された配列 Points[] の各要素 Point、配列の先頭から最後まで、第 2 引数としてされたデリゲートを通じで ProductGT10 メソッドに引数として渡し、ProductGT10 メソッドが true を返した時点で作業を終了して、その時の Point を Find<T> メソッドの戻り値として返しているいるということです。

1

追記

2019/09/20 07:18

投稿

退会済みユーザー
answer CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  docs.microsoft.com にはその説明は見つからないので、以下に抜粋しておきます。
4
4
 
5
+ "Predicate<T> は、渡されたオブジェクトがデリゲートで定義された条件と一致した場合にtrue を返すメソッドのデリゲートです。array の要素は、それぞれ Predicate<T> に渡されます。この処理は、Array 内の先頭の要素から、最後の要素まで繰り返し行われます。一致する要素が見つかった時点で処理が終了します。"
6
+
5
7
  "Predicate<T> デリゲートと Find<T> ジェネリック メソッドを使用して、Point 構造体の配列を検索するコード例を次に示します。X フィールドと Y フィールドの積が 100,000 を超える場合は、デリゲートが表す ProductGT10 メソッドから true が返ります。Find<T> メソッドでは、配列の各要素に対してデリゲートが呼び出され、テスト条件を満たす最初のポイントが返されます。"
6
8
 
7
9
  > ProductGT10の引数がどのように決定されているのか仕組みがわかりません