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

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

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

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

Unity

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

Q&A

2回答

1671閲覧

Unity C# にて動的なダウンキャストを行いたい

Hiiragi3

総合スコア6

C#

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

Unity

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

0グッド

0クリップ

投稿2017/08/24 06:19

編集2017/08/24 12:41

###前提・実現したいこと
Unity 2017.1.0p4 で .NET4.6 を設定すれば利用可能になる dynamic キーワードど同等なことが、Unity 5.5.0f3 周辺の環境でも実現できるようになりたい。

下記エラーの対応によって dynamic が使えるようになればそれでも良いですし、それ以外の方法があれば知りたいです。
(まぁ正直、用意されている内部構造を変えれるとしても当然推奨はされないとは思いますが・・・)

(追記:dynamic を使えるようにする手法はやはり問題がありそうなので候補から外します)

###該当のソースコード
(情報が足らない部分があったので追記しました)

C#

1using UnityEngine; 2 3public class TestClassAlgorithmMain : MonoBehaviour 4{ 5 6 void Start() 7 { 8 // アップキャスト 9 ClassA instance = new ClassC(); 10 11 // (疑問)アップキャストされた変数を、明示的にではなく、何かしらの手法で動的にダウンキャストした上でメソッドに渡したい 12 // 或いは、メソッドに渡った段階で暗黙的にダウンキャストされた状態にしたい 13 // ClassB, ClassC という文字列をこれ以上記述しない方法を模索したい。 14 15 // 失敗例 16 // Hoge((ClassB)instance); // 明示的なので、今回の要件には不適切 17 // Hoge(instance as ClassB); // 同上 18 19 // 条件付き成功例 20 // Hoge((dynamic)instance); // Unity2017.1.0p4 で .NET4.6 を使えるようにすれば動く 21 22 Hoge(instance); // error 23 Moge(instance); // error 24 } 25 26 // 下記の Hoge() と Moge() は変更しない 27 void Hoge(ClassB instance) 28 { 29 instance.Hoge(); 30 } 31 32 void Moge(ClassC instance) 33 { 34 instance.Moge(); 35 } 36} 37 38 39public class ClassA : Object { } 40 41public class ClassB : ClassA 42{ 43 public void Hoge() 44 { 45 Debug.Log("hogehogehoge"); 46 } 47} 48 49public class ClassC : ClassB 50{ 51 public void Moge() 52 { 53 Debug.Log("mogemogemoge"); 54 } 55}

###エラー

後述のソースコードをそのまま書くと下記エラーが出る - Assets/TestClassAlgorythmMain.cs(13,9): error CS1502: The best overloaded method match for `TestClassAlgorythmMain.Hoge(ClassB)' has some invalid arguments - Assets/TestClassAlgorythmMain.cs(13,14): error CS1503: Argument `#1' cannot convert `ClassA' expression to type `ClassB' Unity 5.5.0f3 で(dynamic)を使うと、Unity 上で二つのエラーが出る - Assets/TestClassAlgorythmMain.cs(12,15): error CS1980: Dynamic keyword requires `System.Runtime.CompilerServices.DynamicAttribute' to be defined. Are you missing System.Core.dll assembly reference? - Assets/TestClassAlgorythmMain.cs(12,9): error CS1969: Dynamic operation cannot be compiled without `Microsoft.CSharp.dll' assembly reference

###試したこと
リフレクション関連を使えば何か出来るかと思ったが、そもそも C# 初心者レベルなので作法が良く分からなかった。

###補足情報(言語/FW/ツール等のバージョンなど)
Unity2017.1.0p4, Unity 5.5.0f3
共に C#

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

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

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

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

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

MMashiro

2017/08/28 02:31

Hoge, Moge関数は変更しないと書かれていますが、一切変更不可って事でしょうか
Hiiragi3

2017/08/28 03:17

中身は変更不可能になります。その引数に ClasB、或いは ClassC のインスタンスを渡したいということになります。
guest

回答2

0

as演算子を使用してはいかがでしょうか。
as演算子でダウンキャストできない場合はnullに変換されます。

C#

1ClassA instance = new ClassB(); 2Hoge(instance as ClassB);

(追記)
「Hoge()が実装されているインスタンスならそれを実行する」というのであれば、interfaceを使用します。
ClassA継承にかかわらず、IHasHogeインターフェイスを実装していればキャストされます。

C#

1public class TestClassAlgorythmMain : MonoBehaviour { 2 void StartX () 3 { 4 // アップキャスト 5 ClassA instance = new ClassB(); 6 7 Hoge(instance); 8 } 9 10 void Hoge(object instance) 11 { 12 var p = instance as IHasHoge; 13 if (p != null) 14 { 15 p.Hoge(); 16 } 17 } 18} 19 20public interface IHasHoge 21{ 22 void Hoge(); 23} 24 25public class ClassA : Object {} 26 27public class ClassB : ClassA, IHasHoge 28{ 29 public void Hoge() 30 { 31 Debug.Log("hogehogehoge"); 32 } 33} 34 35

投稿2017/08/24 11:28

編集2017/08/24 12:29
neelabo

総合スコア60

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

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

Hiiragi3

2017/08/24 11:50

ご回答ありがとうございます。 すみません、情報が足らなかったようです。 この場合、ClassB という文字列を明示的に記述することなく、Hoge() に正常に渡したい、ということでした。 例えば Hoge(instance as ClassB); であれば、この「ClassB」という定義を、直接書かず、どのようにかして動的に持ってくることができるか、ということになります。
neelabo

2017/08/24 12:32

目的とは合わないかもしれませんが、特定のメソッドが実装されているならそれを呼び出したい、という目的ならばinterfaceを使用する方法もありますので、追記いたしました。
Hiiragi3

2017/08/24 12:38

ありがとうございます。interface を使うのは思いつきませんでした。 結果的には明示的なキャストを実装しなければならないので目的にはそぐわないのですが、参考にさせていただきます。
guest

0

【Unity】UnityでC#5.0と6.0の機能を使用できるようにする
http://baba-s.hatenablog.com/entry/2016/06/27/100000
こういうのを見つけました。やはり問題もあるらしく、あまりこういった手法は使わないほうが良いかもしれませんね。WebGL が対応プラットフォームにないのも気になるところですが・・・。

一応 Unity5.5.0f3 のプロジェクトに入れてみましたが、dynamic 自体に関するエラーは出なくなりましたが、別のエラーが出ました。

Missing compiler required member "Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create"

Unity においてのこの解決策はぱっと調べた感じ判らなかったのと、上記の問題点もあるということで、解決候補からは外したいと思います。

投稿2017/08/24 10:49

Hiiragi3

総合スコア6

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問