🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Delegates

Delegatesとは、オブジェクト指向型プログラミングにおいて、あるオブジェクトの操作を一部の他のオブジェクトに代替させる手法のこと。オブジェクトは他のデリゲートに頼って関数を実行することができます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

3回答

2771閲覧

デリゲートの効果的な使用方法について

mushipan0929

総合スコア56

Delegates

Delegatesとは、オブジェクト指向型プログラミングにおいて、あるオブジェクトの操作を一部の他のオブジェクトに代替させる手法のこと。オブジェクトは他のデリゲートに頼って関数を実行することができます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

1クリップ

投稿2020/12/17 08:05

前提・実現したいこと

現在、デリゲートについて勉強しています。
実装方法については理解出来ましたが、デリゲートの特徴である**「実行するメソッドを変数に保存でき、後からまとめて実行出来る」**
自分はこの機能をどう生かしていけば良いのか理解できませんでした...
どういった場面で使うと効果的なのか?また無理をして使うような機能ではないのか?お聞きしたいです。

同じ挙動をする2つのコードを下記に記載しています
目的:Mainクラス内のhpを減らす
例1はデリゲート使用、例2は未使用です。

例2の方が個人的に馴染みがありとっつきやすいのもありますが
ここまでコードが長くなる例1には疑問しか湧いてこないです

該当のソースコード

・例1

C#

1public class Event : MonoBehaviour 2 { 3 Main main = new Main(); 4 5 private void Start() 6 { 7 main.hp = 100; 8 9 Debug.Log("現在HP: " + main.hp); 10 11 // メソッドの保存 12 main.onDamage += main.TakeDamage; 13 main.onDamage += main.TakeDamage; 14 main.onDamage += main.TakeDamage; 15 16 // 3回10ダメージ与える 17 main.PlayDelegate(10); 18 19 Debug.Log("現在HP: " + main.hp); 20 } 21 } 22 23 public class Main 24 { 25 // デリゲート型の定義 26 public delegate void OnDamageDelegate(int damage); 27 // デリゲート型変数の宣言 28 // event をつけるとクラス内でのみ呼び出せるようになる 29 public event OnDamageDelegate onDamage; 30 31 public int hp { get; set; } 32 33 public void TakeDamage(int damage) 34 { 35 hp -= damage; 36 Debug.Log(damage + "ダメージ"); 37 } 38 39 public void PlayDelegate(int damage) 40 { 41 onDamage(damage); 42 } 43 }

・例2

C#

1public class Event : MonoBehaviour 2 { 3 Main main = new Main(); 4 5 private void Start() 6 { 7 main.hp = 100; 8 9 Debug.Log("現在HP: " + main.hp); 10 11 // メソッドの実行 12 // 3回10ダメージ与える 13 main.TakeDamage(10); 14 main.TakeDamage(10); 15 main.TakeDamage(10); 16 17 Debug.Log("現在HP: " + main.hp); 18 } 19 } 20 21 public class Main 22 { 23 public int hp { get; set; } 24 25 public void TakeDamage(int damage) 26 { 27 hp -= damage; 28 Debug.Log(damage + "ダメージ"); 29 } 30 }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2020/12/18 22:17

> 実行するメソッドを変数に保存でき、後からまとめて実行出来る デリゲートの使い方としては珍しい使い方です。複数の関数を登録したい場合は一つのデリゲートに登録するのではなく、List<T> などのもっと扱いやすいコレクションを使用するのが一般的です。マルチキャストはほぼイベント専用と考えて差し支えないでしょう。
guest

回答3

0

また無理をして使うような機能ではないのか?

そうです。無理して使う機能ではありません。使うべきところで使いましょう。
すべての機能について言えることです。
ただ、「無理して」が「一生懸命勉強して」の意だったら勉強はしたほうがいいです。

どういった場面で使うと効果的なのか?

実感するには実際にデリゲートを要求するメソッドなどを使ってみるのが手っ取り早いです。
Linqの各種メソッドやボタンのクリックイベントとかです。

投稿2020/12/18 02:01

ozwk

総合スコア13551

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mushipan0929

2020/12/19 01:23

回答ありがとうございます。 確かに仰る通り知っていて腐る知識は無いと思います ただ時折、どう使えば良いのか、今の自分に扱えるものだろうか?とか考えてしまい勉強そのものに疑問を呈してしまう時があるんですよね... Linqやボタンのクリックイベント等まだまだ触った事のないものだらけですが、少しずつ学習していこうと思います。
guest

0

ベストアンサー

用途は色々ありますが、個人的によく使うのが、

  • イベント、コールバック処理を注入する

処理を始めるタイミング、引数のお膳立てまではするけど、処理の実装は利用者側で決めてという場合。
ボタンクリックのイベントとか、 Regex.Replace のサンプルとか
継承でも実装できなくはないけど、デリゲートだと全然関係ないクラスからでも注入できる。

  • 実装が複数あり、切り替える事がある

Hoge(a, b)を高速化したFastHoge(a, b)、安全性の高いSecureHoge(a, b)みたいなのがあったとして、どちらを使うか不確定の場合、呼び出しをデリゲート経由にしておくと切り替えやすい。

インターフェース定義して、それに沿ったクラス作って注入とかでも実現できますが、そこまでするのも大袈裟だなーという場合、とりあえずデリゲートでみたいなのはあります。

質問の例だと、そもそもクラスの役割が明確ではないので、どちらがいいのか決めれる段階ではないと思います。その実装をする事で、何を実現させたいかが重要です。

投稿2020/12/18 01:32

編集2020/12/18 01:51
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mushipan0929

2020/12/19 01:18

回答ありがとうございます。 >イベント、コールバック処理を注入する >実装が複数あり、切り替える事がある 現在ゲーム制作をしているのですが、かなり思い当たる節があるので これを機に修正したいと思います。
退会済みユーザー

退会済みユーザー

2020/12/21 00:24 編集

いくつか回答ついているのに12/19以降放置されてますが、結局のところ問題は解決したのでしょうか?具体的な問題が残っているのであれば質問に追記し、もう解決の方向性が決まったのであれば終了させてください。
mushipan0929

2020/12/26 02:47

そうでしたね、すっかり忘れておりました... 今からベストアンサーを決めたいと思います。
guest

0

どういった場面で使う

あるタイミングで「何か」をすべきであろうが,行うことが具体的に何なのかに関して

  • その型のみではわからない,それを決めるのはその型の範疇ではない
  • やるべきことが動的に変わる

等といった場合.

例えば,イベントハンドラとか.
イベントが起こったときにきっと何かしたいだろう,というのはわかる.
でも,何をすべきなのかはアプリケーション次第だから,実装できない.

投稿2020/12/17 08:12

編集2020/12/17 08:16
fana

総合スコア11985

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mushipan0929

2020/12/17 13:48

なるほど... 回答ありがとうございます。 例えば、歩く、ジャンプする、走る動作をする関数がそれぞれあったとして 歩きながらジャンプする関数を作りたい時には、歩く+ジャンプする関数を代入で実行 走りながらジャンプする関数を作りたい時には、走る+ジャンプする関数を代入で実行 みたいな感じで使っていくようなものですかね...?(例えが不自由で申し訳ないです)
fana

2020/12/18 01:31

正直,その例えがよくわからないです… --- なんだろう,例えば,画面に"5"と表示したいときに,コードを Output( 5 ); とか書くのだとしよう. 常に "5" とだけ表示したいならばこれで完全にOKである. しかし,その時々で表示を変えたい:"4"とか"100"とかも表示したい という場合,この書き方だと if( "4" と表示したい ){ Output( 4 ); } else if( "5" 〃 ){ Output( 5 ); } else if( "100" 〃 ){ Output( 100 ); } ... とかいう非常に残念なコードになるではないか. 書くのもつらいし,それ以前にそもそもこの方式だと「表示したくなるパターンは{ 4, 5, 100 }の他にあとどれだけあるのか?」っていうのを,このifの羅列を実装している時点で完全に知っている必要もある. ちょっと考えて,「変数」とかいうやつを導入してみる.すると,表示箇所のコードは Output( a ); //※事前に変数aの値を所望の値にしておく だけで済むではないか. 上記は「値」を変数として扱って便利になったわけだが, 同じ感じで,「処理」を変数として扱うのがdelegateだと考えればよいのではないだろうか. すなわち, if( 処理Aをしたい ){ A(); } else if( 処理B〃 ){ B(); } ... を, F(); //Fがdelegateだとして,事前にやりたい処理(群)を入れておく. と書けるわけだ. もちろん,delegateではない手段でも実現し得るならば,方法を見比べて,より(何らかの意味で)良い方法を使えばいい.
fana

2020/12/18 01:41

上記ではifの羅列を書いたけども,別に switch とか済む話であれば,素直にそう書いてもいいわけで. その「歩く」とか「ジャンプする」という処理の組み合わせパターンが確定しているなら delegate 等を持ちださなくてもよいかもしれない. 無理矢理持ち込むと,まさに > 例1には疑問しか湧いてこない みたくなる.
mushipan0929

2020/12/19 00:30

詳しくありがとうございます! 自分の例えはあらかじめ行われる処理を全て把握していてかつ 複数の関数を呼び出す必要がある時にDelegateを使えば呼び出すときに1行でコンパクトに呼び出せる...といった考えでした。 上記の例え、とても分かりやすかったです。 改めて、ありがとうございました。
Zuishin

2020/12/19 01:23 編集

自分で考えた思いつきの使い方を「自分はこの機能をどう生かしていけば良いのか理解できませんでした...」と人に丸投げするのが間違っています。普通そんなことはしません。 尋ねられた方も「理解できないのはこっちだ」と思ったことでしょう。
mushipan0929

2020/12/19 01:26

> Zuishinさん なるほど...失礼致しました。 もしも学習した物の用途が理解できなかった場合どう行動するのが適切なのでしょうか..? Teratailで丸投げな質問は非推奨されているのは存じていますが、今の自分ではこういった質問を投げかける事しか思いつきませんでした。
Zuishin

2020/12/19 01:34

学習したことではなく、あなたの思いつきですよね?
mushipan0929

2020/12/19 01:37

いえいえ、自分で全て思いついたわけではなく 色々なサイトを見よう見まねで勉強しましたので大丈夫です。
Zuishin

2020/12/19 01:39

大丈夫と判断したのはあなたですよね? 私からは全然大丈夫には見えません。 「カナヅチが水に沈むという特徴がどこで役に立つか理解できません」と言われたら、言われた方は「はぁ?」となります。
mushipan0929

2020/12/19 01:47 編集

申し訳ないです、ちょっと自分の理解が.. 使い方が分からない道具の使い方を他人に聞く事はおかしい 使い方が分からない道具の使い方が思いつかない原因を他人に聞く事はおかしい という事でしょうか?恐らく違うような気もしますが...
Zuishin

2020/12/19 02:58

道具の本来の使い方ではないものを書いた指南書を頼りにしているのが間違っているので、ちゃんとした情報にあたって体系的に学ぶのが良いと思います。
mushipan0929

2020/12/19 03:04

なるほど!理解出来ました。 確かにネットで調べるだけ調べて判断することが多くなっているような気がします... もう少し書籍なども買い読んでみることにします! 長々とありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問