質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.50%
C#

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

Unity

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

Q&A

解決済

2回答

1064閲覧

ジェネリックなメソッドで、受け取った型に応じて処理をしたい

toorai

総合スコア16

C#

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

Unity

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

0グッド

0クリップ

投稿2023/05/16 04:15

編集2023/05/18 06:59

実現したいこと

・ジェネリックなメソッドで、指定した型が渡された際に別のジェネリックメソッドを呼びたい

前提

実行する際に型を指定するメソッドがあります。
その型が条件を満たしている時のみ、別のジェネリックメソッドを呼びたいです。

以下のコードの説明
MethodClass.Mehod<T>()を呼んだ際に、TがBaseClassを継承しているときだけGenericMethod<T>()を呼ぶ
・MethodClass.Method<TestClassA>() =>GenericMethod<T>()を実行する
・MethodClass.Method<TestClassB>() =>GenericMethod<T>()を実行しない

ソースコード

C#

1public abstract class BaseClass { } 2public class TestClassA : BaseClass { } 3public class TestClassB { } 4 5public static class MethodClass 6{ 7 public static void Method<T>() 8 { 9 //ここで、TがBaseClassを継承しているならGenericMethod<T>()を呼びたい 10 } 11 12 static void GenericMethod<T>() where T : BaseClass 13 { 14 } 15}

呼び出し側ソースコード

C#

1public class CallClass : MonoBehaviour 2{ 3 private void Start() 4 { 5 MethodClass.Method<TestClassA>(); 6 MethodClass.Method<TestClassB>(); 7 } 8}

試したこと

以下のようにTがBaseClassを継承しているかは判定できます。
ただ、そこからどのようにGenericMethod<T>()を呼ぶのかが不明です。
(TがBaseClassを継承していることを、if文内で保証できない)

C#

1public class CallClass : MonoBehaviour 2{ 3 public static void Method<T>() 4 { 5 if(typeof(T).IsSubclassOf(typeof(BaseClass))) 6 { 7 //ここでGenericMethodを呼びたい 8 } 9 } 10}

追記

一度自己解決として質問を閉じましたが、解決策とした方法では問題があったため再度回答受付中に変更しました。
解決策とした方法では、GenericMethod内でTの型を利用できないため問題が生じました。

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

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

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

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

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

Zuishin

2023/05/16 04:19

引数の型によって同名のメソッドを呼び分けるにはオーバーロードを使うのが簡単です。
toorai

2023/05/16 04:43

コメントいただきありがとうございます。 今回のコードでは引数がないため、そもそもジェネリック型を使う必要性がないことに気づきました。 自己解決として、質問を閉じます。
Zuishin

2023/05/16 22:40

Type.IsAssignableFrom と Type.MakeGenericMethod でその場はしのげます。 間違いなく設計が間違っているので、本来の目的を書けばちゃんとした解決方法が得られると思いますが。
toorai

2023/05/17 02:02

リフレクションを使用すれば、とりあえずは解決できるのですね。 参考にいたします。
guest

回答2

0

型推論のために GenericMethod<T>() をラップしたメソッド GenericMethodWapper<T>(T unused) where T: BaseClass を作ってみるとか?バッドノウハウの類ですが...

Unity環境無いので通常のコンソールアプリですが、こんな感じで。

C#

1using System; 2 3public class Program { 4 public static void Main(){ 5 Method<TestClassA>(); 6 Method<TestClassB>(); 7 } 8 9 private static void Method<T>() { 10 if(typeof(T).IsSubclassOf(typeof(BaseClass))) { 11 // 型推論のためだけなので、引数は型が BaseClass なら何でもいい 12 GenericMethodWrapper(null as BaseClass); 13 } 14 else { 15 Console.WriteLine($"Method<{typeof(T).Name}>"); 16 } 17 } 18 19 // T を型推論で決定させるためだけのラッパーメソッド 20 private static void GenericMethodWrapper<T>(T unused) where T: BaseClass { 21 GenericMethod<T>(); 22 } 23 24 private static void GenericMethod<T>() where T: BaseClass { 25 Console.WriteLine($"GenericMethod<{typeof(T).Name}>"); 26 } 27} 28 29public abstract class BaseClass { } 30public class TestClassA : BaseClass { } 31public class TestClassB { }

投稿2023/05/16 15:21

編集2023/05/16 15:23
draq

総合スコア2573

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

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

toorai

2023/05/17 01:56

型を特定するために、メソッド内では使わない引数を指定する方法と理解しました。 ご回答いただきありがとうございました。
guest

0

自己解決

あまり良い方法ではないようですが、今回はZuishinさんのコメントを参考にリフレクションで対応しました。
以下が修正した部分です。

C#

1using System.Reflection; 2 3--- 4 5public static void Method<T>() 6{ 7 if (typeof(BaseClass).IsAssignableFrom(typeof(T))) 8 { 9 var mInfo = typeof(MethodClass).GetMethod("GenericMethod", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); 10 var gmInfo = mInfo.MakeGenericMethod(typeof(T)); 11 gmInfo.Invoke(null, new object[0] { }); 12 } 13}

以下過去コメント


一度自己解決としましたが、解決策に問題があったため再度回答受付中に変更しました。
解決策とした方法では、GenericMethod内でTの型を利用できないため問題が生じました。
以下は自己解決とした際の過去のコメントです。


GenericMehoodに引数がないため、あえてジェネリック型にする意味がないことに気づきました。
GenericMethod()としたうえで、IsSubclassOfによる判定によって呼ぶようにします。

投稿2023/05/16 04:47

編集2023/05/17 02:27
toorai

総合スコア16

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問